diff options
Diffstat (limited to 'src')
216 files changed, 4362 insertions, 3152 deletions
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h index 03f8e2d71a..734e779c70 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h @@ -359,6 +359,12 @@ public: } } + void mul32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + mul32(dataTempRegister, dest); + } + void neg32(RegisterID srcDest) { m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest); @@ -420,6 +426,12 @@ public: store32(dataTempRegister, dest.m_ptr); } + void or32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + or32(dataTempRegister, dest); + } + void rshift32(RegisterID shiftAmount, RegisterID dest) { m_assembler.srav(dest, dest, shiftAmount); @@ -615,6 +627,12 @@ public: m_assembler.xorInsn(dest, src, immTempRegister); } + void xor32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + xor32(dataTempRegister, dest); + } + void sqrtDouble(FPRegisterID src, FPRegisterID dst) { m_assembler.sqrtd(dst, src); @@ -2519,6 +2537,18 @@ public: m_assembler.cvtdw(dest, fpTempRegister); } + void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID scratch) + { + m_assembler.mtc1(src, fpTempRegister); + m_assembler.bltz(src, 2); + m_assembler.cvtdw(dest, fpTempRegister); + m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 4); + m_assembler.lui(scratch, 0x4f80); + m_assembler.mtc1(scratch, fpTempRegister); + m_assembler.cvtds(fpTempRegister, fpTempRegister); + m_assembler.addd(dest, dest, fpTempRegister); + } + void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) { m_assembler.cvtds(dst, src); @@ -2761,7 +2791,7 @@ public: return CodeLocationLabel(); } - static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*) { UNREACHABLE_FOR_PLATFORM(); } diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp index 80b32e64ef..0f4a5bda54 100644 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp +++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp @@ -788,6 +788,20 @@ QVariant QQuickFolderListModel::get(int idx, const QString &property) const return QVariant(); } +/*! + \qmlmethod int FolderListModel::indexOf(url file) + \since 5.6 + + Get the index of the given file URL if the model contains it, + or -1 if not. +*/ +int QQuickFolderListModel::indexOf(const QUrl &file) const +{ + Q_D(const QQuickFolderListModel); + FileProperty toFind(QFileInfo(file.toLocalFile())); + return d->data.indexOf(toFind); +} + #include "moc_qquickfolderlistmodel.cpp" //![code] diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h index 63ed528556..0001b2fdf3 100644 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.h +++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h @@ -132,6 +132,7 @@ public: Q_INVOKABLE bool isFolder(int index) const; Q_INVOKABLE QVariant get(int idx, const QString &property) const; + Q_INVOKABLE int indexOf(const QUrl &file) const; //![parserstatus] virtual void classBegin(); diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index b0ba3f9228..22a3eed39d 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -126,7 +126,7 @@ public: ~QQmlSqlDatabaseWrapper() { } - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); }; } @@ -214,7 +214,7 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV4::E return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName; } -static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0) +static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0) { Scope scope(v4); @@ -238,15 +238,14 @@ static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, Execut } } -ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty) { - QV4::Scope scope(static_cast<QQmlSqlDatabaseWrapper *>(m)->engine()); Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>()); - QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, static_cast<QQmlSqlDatabaseWrapper *>(m)); + const QQmlSqlDatabaseWrapper *r = static_cast<const QQmlSqlDatabaseWrapper *>(m); if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows) return Object::getIndexed(m, index, hasProperty); - return qmlsqldatabase_rows_index(r, scope.engine, index, hasProperty); + return qmlsqldatabase_rows_index(r, r->engine(), index, hasProperty); } static ReturnedValue qmlsqldatabase_rows_item(CallContext *ctx) @@ -285,13 +284,13 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx) if (query.prepare(sql)) { if (ctx->argc() > 1) { ScopedValue values(scope, ctx->args()[1]); - if (values->asArrayObject()) { + if (values->as<ArrayObject>()) { ScopedArrayObject array(scope, values); quint32 size = array->getLength(); QV4::ScopedValue v(scope); for (quint32 ii = 0; ii < size; ++ii) query.bindValue(ii, scope.engine->toVariant((v = array->getIndexed(ii)), -1)); - } else if (values->asObject()) { + } else if (values->as<Object>()) { ScopedObject object(scope, values); ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly); ScopedValue key(scope); @@ -304,7 +303,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx) if (key->isString()) { query.bindValue(key->stringValue()->toQString(), v); } else { - assert(key->isInteger()); + Q_ASSERT(key->isInteger()); query.bindValue(key->integerValue(), v); } } @@ -401,7 +400,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx) db.transaction(); ScopedCallData callData(scope, 1); - callData->thisObject = scope.engine->globalObject(); + callData->thisObject = scope.engine->globalObject; callData->args[0] = w; TransactionRollback rollbackOnException(&db, &w->d()->inTransaction); @@ -433,7 +432,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database) V4THROW_REFERENCE("Not a SQLDatabase object"); - FunctionObject *callback = ctx->argc() ? ctx->args()[0].asFunctionObject() : 0; + const FunctionObject *callback = ctx->argc() ? ctx->args()[0].as<FunctionObject>() : 0; if (!callback) V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback")); @@ -450,7 +449,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re db.transaction(); if (callback) { ScopedCallData callData(scope, 1); - callData->thisObject = scope.engine->globalObject(); + callData->thisObject = scope.engine->globalObject; callData->args[0] = w; TransactionRollback rollbackOnException(&db, &w->d()->inTransaction); callback->call(callData); @@ -673,7 +672,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) QString dbversion = (v = (*args)[1])->toQStringNoThrow(); QString dbdescription = (v = (*args)[2])->toQStringNoThrow(); int dbestimatedsize = (v = (*args)[3])->toInt32(); - FunctionObject *dbcreationCallback = (v = (*args)[4])->asFunctionObject(); + FunctionObject *dbcreationCallback = (v = (*args)[4])->as<FunctionObject>(); QCryptographicHash md5(QCryptographicHash::Md5); md5.addData(dbname.toUtf8()); @@ -724,7 +723,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) if (created && dbcreationCallback) { Scope scope(ctx); ScopedCallData callData(scope, 1); - callData->thisObject = scope.engine->globalObject(); + callData->thisObject = scope.engine->globalObject; callData->args[0] = db; dbcreationCallback->call(callData); } diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml index 039ee63f07..4c48611e79 100644 --- a/src/imports/testlib/TestCase.qml +++ b/src/imports/testlib/TestCase.qml @@ -613,12 +613,19 @@ Item { \li blue(x, y) Returns the blue channel value of the pixel at \a x, \a y position \li alpha(x, y) Returns the alpha channel value of the pixel at \a x, \a y position \li pixel(x, y) Returns the color value of the pixel at \a x, \a y position + \li equals(image) Returns \c true if this image is identical to \a image - + see \l QImage::operator== (since 5.6) + For example: \code var image = grabImage(rect); compare(image.red(10, 10), 255); compare(image.pixel(20, 20), Qt.rgba(255, 0, 0, 255)); + + rect.width += 10; + var newImage = grabImage(rect); + verify(!newImage.equals(image)); \endcode \endlist diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp index b078edcbc6..832f484c13 100644 --- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp +++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp @@ -36,7 +36,7 @@ #include <qqmlcontext.h> #include <private/qqmlengine_p.h> #include <private/qv8engine_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4engine_p.h> #include <private/qv4object_p.h> diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index 32cde7c126..5e244ba02c 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -370,10 +370,10 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes() } } - NodeHashConstIt it = m_nodes.begin(); + NodeHashConstIt it = m_nodes.cbegin(); rootNode = it.value(); rootNode->setFlag(QSGNode::OwnsMaterial, true); - const NodeHashConstIt cend = m_nodes.end(); + NodeHashConstIt cend = m_nodes.cend(); for (++it; it != cend; ++it) rootNode->appendChildNode(it.value()); diff --git a/src/particles/qquickv4particledata_p.h b/src/particles/qquickv4particledata_p.h index f211ec7e7d..c29c7e1134 100644 --- a/src/particles/qquickv4particledata_p.h +++ b/src/particles/qquickv4particledata_p.h @@ -36,7 +36,7 @@ #include <private/qv8engine_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 63833504f1..cc9da2817a 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -33,7 +33,7 @@ #include "qqmlirbuilder_p.h" -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4compileddata_p.h> #include <private/qqmljsparser_p.h> #include <private/qqmljslexer_p.h> diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 21846775a3..03e2aa295c 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1022,10 +1022,10 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } } - QHash<QString, QStringList>::ConstIterator entry = customSignals.find(propertyName); + QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(propertyName); if (entry == customSignals.constEnd() && propertyName.endsWith(QStringLiteral("Changed"))) { QString alternateName = propertyName.mid(0, propertyName.length() - static_cast<int>(strlen("Changed"))); - entry = customSignals.find(alternateName); + entry = customSignals.constFind(alternateName); } if (entry == customSignals.constEnd()) { diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 9168889c8c..ea82d07e69 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -33,6 +33,7 @@ #include "qv4codegen_p.h" #include "qv4util_p.h" +#include "qv4engine_p.h" #include <QtCore/QCoreApplication> #include <QtCore/QStringList> @@ -43,7 +44,7 @@ #include <QtCore/QStack> #include <private/qqmljsast_p.h> #include <private/qv4string_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #ifndef V4_BOOTSTRAP #include <qv4context_p.h> diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 5d954eb4fc..20db5edaa3 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -33,7 +33,7 @@ #include "qv4compileddata_p.h" #include "qv4jsir_p.h" -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #ifndef V4_BOOTSTRAP #include <private/qv4engine_p.h> #include <private/qv4function_p.h> diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 450889c275..9e4c7560c1 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -35,7 +35,7 @@ #include <qv4compileddata_p.h> #include <qv4isel_p.h> #include <private/qv4string_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QV4::Compiler::StringTableGenerator::StringTableGenerator() { @@ -44,8 +44,8 @@ QV4::Compiler::StringTableGenerator::StringTableGenerator() int QV4::Compiler::StringTableGenerator::registerString(const QString &str) { - QHash<QString, int>::ConstIterator it = stringToId.find(str); - if (it != stringToId.end()) + QHash<QString, int>::ConstIterator it = stringToId.constFind(str); + if (it != stringToId.cend()) return *it; stringToId.insert(str, strings.size()); strings.append(str); diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index eb78a0c054..b084c9a1fc 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1444,7 +1444,7 @@ ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &in void InstructionSelection::patchJumpAddresses() { typedef QHash<IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator PatchIt; - for (PatchIt i = _patches.begin(), ei = _patches.end(); i != ei; ++i) { + for (PatchIt i = _patches.cbegin(), ei = _patches.cend(); i != ei; ++i) { Q_ASSERT(_addrs.contains(i.key())); ptrdiff_t target = _addrs.value(i.key()); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 54b184b4eb..46b9c784d2 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -36,7 +36,7 @@ #include "qv4jsir_p.h" #include "qv4isel_p.h" #include "qv4isel_util_p.h" -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #ifndef V4_BOOTSTRAP #include <private/qqmlpropertycache_p.h> #endif diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp index b0302181ee..d79028b3fe 100644 --- a/src/qml/debugger/qqmldebugserver.cpp +++ b/src/qml/debugger/qqmldebugserver.cpp @@ -422,8 +422,8 @@ QQmlDebugServer::QQmlDebugServer() QString pluginName; QStringList lstjsDebugArguments = appD->qmljsDebugArgumentsString() .split(QLatin1Char(',')); - QStringList::const_iterator argsItEnd = lstjsDebugArguments.end(); - QStringList::const_iterator argsIt = lstjsDebugArguments.begin(); + QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend(); + QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin(); for (; argsIt != argsItEnd; ++argsIt) { const QString strArgument = *argsIt; if (strArgument.startsWith(QLatin1String("port:"))) { diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index da01d00f17..a7ef450606 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -644,11 +644,9 @@ bool QQmlEngineDebugService::setBinding(int objectId, filename, line, column); QQmlPropertyPrivate::takeSignalExpression(property, qmlExpression); } else if (property.isProperty()) { - QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);; + QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column); binding->setTarget(property); - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, binding); - if (oldBinding) - oldBinding->destroy(); + QQmlPropertyPrivate::setBinding(binding); binding->update(); } else { ok = false; @@ -679,12 +677,7 @@ bool QQmlEngineDebugService::resetBinding(int objectId, const QString &propertyN if (object->property(parentProperty.toLatin1()).isValid()) { QQmlProperty property(object, propertyName); - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(property); - if (oldBinding) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, 0); - if (oldBinding) - oldBinding->destroy(); - } + QQmlPropertyPrivate::removeBinding(property, QQmlPropertyPrivate::DestroyOldBinding); if (property.isResettable()) { // Note: this will reset the property in any case, without regard to states // Right now almost no QQuickItem has reset methods for its properties (with the diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp index 32b7b38285..e736dd9059 100644 --- a/src/qml/debugger/qv4debugservice.cpp +++ b/src/qml/debugger/qv4debugservice.cpp @@ -230,7 +230,7 @@ protected: virtual void addObject(const QString &name, const QV4::Value &value) { QV4::Scope scope(engine()); - QV4::ScopedObject obj(scope, value.asObject()); + QV4::ScopedObject obj(scope, value.as<QV4::Object>()); int ref = cachedObjectRef(obj); if (ref != -1) { diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 09e5b14c97..b5765b5705 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -241,16 +241,16 @@ void Assembler::enterStandardStackFrame(const RegisterInformation ®ularRegist subPtr(TrustedImm32(frameSize), StackPointerRegister); Address slotAddr(StackFrameRegister, 0); - for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) { - Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister()); - slotAddr.offset -= RegisterSize; - storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr); - } for (int i = 0, ei = fpRegistersToSave.size(); i < ei; ++i) { Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint()); slotAddr.offset -= sizeof(double); JSC::MacroAssembler::storeDouble(fpRegistersToSave.at(i).reg<FPRegisterID>(), slotAddr); } + for (int i = 0, ei = regularRegistersToSave.size(); i < ei; ++i) { + Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister()); + slotAddr.offset -= RegisterSize; + storePtr(regularRegistersToSave.at(i).reg<RegisterID>(), slotAddr); + } } void Assembler::leaveStandardStackFrame(const RegisterInformation ®ularRegistersToSave, @@ -259,16 +259,16 @@ void Assembler::leaveStandardStackFrame(const RegisterInformation ®ularRegist Address slotAddr(StackFrameRegister, -regularRegistersToSave.size() * RegisterSize - fpRegistersToSave.size() * sizeof(double)); // restore the callee saved registers - for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) { - Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint()); - JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>()); - slotAddr.offset += sizeof(double); - } for (int i = regularRegistersToSave.size() - 1; i >= 0; --i) { Q_ASSERT(regularRegistersToSave.at(i).isRegularRegister()); loadPtr(slotAddr, regularRegistersToSave.at(i).reg<RegisterID>()); slotAddr.offset += RegisterSize; } + for (int i = fpRegistersToSave.size() - 1; i >= 0; --i) { + Q_ASSERT(fpRegistersToSave.at(i).isFloatingPoint()); + JSC::MacroAssembler::loadDouble(slotAddr, fpRegistersToSave.at(i).reg<FPRegisterID>()); + slotAddr.offset += sizeof(double); + } Q_ASSERT(slotAddr.offset == 0); diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 3b65acb26c..f4b44ce882 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -565,6 +565,8 @@ public: moveIntsToDouble(JSC::ARMRegisters::r0, JSC::ARMRegisters::r1, dest, FPGpr0); #elif defined(Q_PROCESSOR_X86) moveIntsToDouble(JSC::X86Registers::eax, JSC::X86Registers::edx, dest, FPGpr0); +#elif defined(Q_PROCESSOR_MIPS) + moveIntsToDouble(JSC::MIPSRegisters::v0, JSC::MIPSRegisters::v1, dest, FPGpr0); #else subPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister); Pointer tmp(StackPointerRegister, 0); @@ -595,6 +597,14 @@ public: destination.offset += 4; store32(JSC::ARMRegisters::r1, destination); } +#elif defined(Q_PROCESSOR_MIPS) + void storeReturnValue(const Pointer &dest) + { + Pointer destination = dest; + store32(JSC::MIPSRegisters::v0, destination); + destination.offset += 4; + store32(JSC::MIPSRegisters::v1, destination); + } #endif void storeReturnValue(IR::Expr *target) @@ -820,6 +830,8 @@ public: else #if OS(WINDOWS) && CPU(X86_64) loadArgumentOnStack<argumentNumber>(value, argumentNumber); +#elif CPU(MIPS) // Stack space for 4 arguments needs to be allocated for MIPS platforms. + loadArgumentOnStack<argumentNumber>(value, argumentNumber + 4); #else // Sanity: loadArgumentOnStack<argumentNumber - RegisterArgumentCount>(value, argumentNumber); #endif diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp index c6c8023cd7..e4a2846f32 100644 --- a/src/qml/jit/qv4binop.cpp +++ b/src/qml/jit/qv4binop.cpp @@ -415,8 +415,8 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *ta case IR::OpAdd: as->add32(l, r, targetReg); break; case IR::OpMul: as->mul32(l, r, targetReg); break; -#if CPU(ARM) || CPU(X86) || CPU(X86_64) - // The ARM assembler will generate an and with 0x1f for us, and Intel will do it on the CPU. +#if CPU(ARM) || CPU(X86) || CPU(X86_64) || CPU(MIPS) + // The ARM assembler will generate an and with 0x1f for us, MIPS and Intel will do it on the CPU. case IR::OpLShift: as->lshift32(l, r, targetReg); break; case IR::OpRShift: as->rshift32(l, r, targetReg); break; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index da511cd1eb..236422c5fd 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -1383,11 +1383,14 @@ void InstructionSelection::visitRet(IR::Ret *s) // this only happens if the method doesn't have a return statement and can // only exit through an exception } else if (IR::Temp *t = s->expr->asTemp()) { -#if CPU(X86) || CPU(ARM) +#if CPU(X86) || CPU(ARM) || CPU(MIPS) # if CPU(X86) Assembler::RegisterID lowReg = JSC::X86Registers::eax; Assembler::RegisterID highReg = JSC::X86Registers::edx; +# elif CPU(MIPS) + Assembler::RegisterID lowReg = JSC::MIPSRegisters::v0; + Assembler::RegisterID highReg = JSC::MIPSRegisters::v1; # else // CPU(ARM) Assembler::RegisterID lowReg = JSC::ARMRegisters::r0; Assembler::RegisterID highReg = JSC::ARMRegisters::r1; @@ -1477,6 +1480,9 @@ void InstructionSelection::visitRet(IR::Ret *s) #elif CPU(ARM) _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0); _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1); +#elif CPU(MIPS) + _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::MIPSRegisters::v0); + _as->move(Assembler::TrustedImm32(retVal.tag), JSC::MIPSRegisters::v1); #else _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister); #endif @@ -1504,6 +1510,9 @@ void InstructionSelection::visitRet(IR::Ret *s) #elif CPU(ARM) _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::ARMRegisters::r0); _as->move(Assembler::TrustedImm32(retVal.tag), JSC::ARMRegisters::r1); +#elif CPU(MIPS) + _as->move(Assembler::TrustedImm32(retVal.int_32), JSC::MIPSRegisters::v0); + _as->move(Assembler::TrustedImm32(retVal.tag), JSC::MIPSRegisters::v1); #else _as->move(Assembler::TrustedImm64(retVal.val), Assembler::ReturnValueRegister); #endif diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index ae06a99d2a..48b7badd56 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -35,7 +35,7 @@ #include <QtCore/QDebug> #include "qv4regalloc_p.h" #include "qv4alloca_p.h" -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <algorithm> #if defined(Q_CC_MINGW) diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h index 05741f0ae5..76c768e4f9 100644 --- a/src/qml/jit/qv4targetplatform_p.h +++ b/src/qml/jit/qv4targetplatform_p.h @@ -346,6 +346,71 @@ public: static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::ARMRegisters::lr); } #endif // Linux on ARM (32 bit) +#if defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX) + enum { RegAllocIsSupported = 1 }; + + static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::MIPSRegisters::fp; + static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::MIPSRegisters::sp; + static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::MIPSRegisters::s0; + static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::MIPSRegisters::s1; + static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::MIPSRegisters::v0; + static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::MIPSRegisters::s2; + static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::MIPSRegisters::f0; + static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::MIPSRegisters::f2; + + static RegisterInformation getPlatformRegisterInfo() + { + typedef RegisterInfo RI; + return RegisterInformation() + // Note: t0, t1, t2, t3 and f16 are already used by MacroAssemblerMIPS. + << RI(JSC::MIPSRegisters::t4, QStringLiteral("t4"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::t5, QStringLiteral("t5"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::t6, QStringLiteral("t6"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::t7, QStringLiteral("t7"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::t8, QStringLiteral("t8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::s0, QStringLiteral("s0"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) + << RI(JSC::MIPSRegisters::s1, QStringLiteral("s1"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) + << RI(JSC::MIPSRegisters::s2, QStringLiteral("s2"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) + << RI(JSC::MIPSRegisters::s3, QStringLiteral("s3"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f4, QStringLiteral("f4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f6, QStringLiteral("f6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f8, QStringLiteral("f8"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f10, QStringLiteral("f10"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f18, QStringLiteral("f18"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f20, QStringLiteral("f20"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f22, QStringLiteral("f22"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f24, QStringLiteral("f24"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f26, QStringLiteral("f26"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) + << RI(JSC::MIPSRegisters::f28, QStringLiteral("f28"), RI::FloatingPointRegister, RI::CalleeSaved, RI::RegAlloc) + ; + } + +#undef HAVE_ALU_OPS_WITH_MEM_OPERAND +#undef VALUE_FITS_IN_REGISTER + static const int RegisterSize = 4; + +#define ARGUMENTS_IN_REGISTERS + static const int RegisterArgumentCount = 4; + static JSC::MacroAssembler::RegisterID registerForArgument(int index) + { + static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = { + JSC::MIPSRegisters::a0, + JSC::MIPSRegisters::a1, + JSC::MIPSRegisters::a2, + JSC::MIPSRegisters::a3 + }; + + Q_ASSERT(index >= 0 && index < RegisterArgumentCount); + return regs[index]; + }; + + static const int StackAlignment = 8; + static const int StackShadowSpace = 4 * RegisterSize; // Stack space for 4 argument registers. + static const int StackSpaceAllocatedUponFunctionEntry = 1 * RegisterSize; // Registers saved in platformEnterStandardStackFrame below. + static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { as->push(JSC::MIPSRegisters::ra); } + static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::MIPSRegisters::ra); } +#endif // Linux on MIPS (32 bit) + public: // utility functions static RegisterInformation getRegisterInfo() { diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index ee27c21aed..a02458b8bd 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -271,7 +271,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object) if (val) obj = val; if (!obj) - obj = scope.engine->globalObject(); + obj = scope.engine->globalObject; #ifndef QT_NO_TRANSLATION obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate); obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp); @@ -281,7 +281,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object) obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp); // string prototype extension - scope.engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), + scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), QV4::GlobalExtensions::method_string_arg); #endif } @@ -414,7 +414,7 @@ QJSValue QJSEngine::globalObject() const { Q_D(const QJSEngine); QV4::Scope scope(d->m_v4Engine); - QV4::ScopedValue v(scope, d->m_v4Engine->globalObject()); + QV4::ScopedValue v(scope, d->m_v4Engine->globalObject); return QJSValue(d->m_v4Engine, v->asReturnedValue()); } diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 50669c46a8..a9333ed8a9 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -37,13 +37,14 @@ #include "qjsengine.h" #include "qjsvalue.h" #include "qjsvalue_p.h" -#include "qv4value_inl_p.h" +#include "qv4value_p.h" #include "qv4object_p.h" #include "qv4functionobject_p.h" #include "qv4dateobject_p.h" #include "qv4runtime_p.h" #include "qv4variantobject_p.h" #include "qv4regexpobject_p.h" +#include "qv4errorobject_p.h" #include "private/qv8engine_p.h" #include <private/qv4mm_p.h> #include <private/qv4scopedvalue_p.h> @@ -317,8 +318,7 @@ bool QJSValue::isError() const QV4::Value *val = QJSValuePrivate::getValue(this); if (!val) return false; - Object *o = val->asObject(); - return o && o->asErrorObject(); + return val->as<ErrorObject>(); } /*! @@ -332,7 +332,7 @@ bool QJSValue::isArray() const QV4::Value *val = QJSValuePrivate::getValue(this); if (!val) return false; - return val->asArrayObject(); + return val->as<ArrayObject>(); } /*! @@ -349,7 +349,7 @@ bool QJSValue::isObject() const QV4::Value *val = QJSValuePrivate::getValue(this); if (!val) return false; - return val->asObject(); + return val->as<Object>(); } /*! @@ -363,7 +363,7 @@ bool QJSValue::isCallable() const QV4::Value *val = QJSValuePrivate::getValue(this); if (!val) return false; - return val->asFunctionObject(); + return val->as<FunctionObject>(); } /*! @@ -589,7 +589,7 @@ QVariant QJSValue::toVariant() const QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch); Q_ASSERT(val); - if (Object *o = val->asObject()) + if (Object *o = val->as<Object>()) return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false); if (val->isString()) @@ -628,7 +628,7 @@ QJSValue QJSValue::call(const QJSValueList &args) if (!val) return QJSValue(); - FunctionObject *f = val->asFunctionObject(); + FunctionObject *f = val->as<FunctionObject>(); if (!f) return QJSValue(); @@ -637,7 +637,7 @@ QJSValue QJSValue::call(const QJSValueList &args) Scope scope(engine); ScopedCallData callData(scope, args.length()); - callData->thisObject = engine->globalObject()->asReturnedValue(); + callData->thisObject = engine->globalObject; for (int i = 0; i < args.size(); ++i) { if (!QJSValuePrivate::checkEngine(engine, args.at(i))) { qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); @@ -679,7 +679,7 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList if (!val) return QJSValue(); - FunctionObject *f = val->asFunctionObject(); + FunctionObject *f = val->as<FunctionObject>(); if (!f) return QJSValue(); @@ -733,7 +733,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) if (!val) return QJSValue(); - FunctionObject *f = val->asFunctionObject(); + FunctionObject *f = val->as<FunctionObject>(); if (!f) return QJSValue(); @@ -789,7 +789,7 @@ QJSValue QJSValue::prototype() const if (!engine) return QJSValue(); QV4::Scope scope(engine); - ScopedObject o(scope, QJSValuePrivate::getValue(this)->asObject()); + ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<Object>()); if (!o) return QJSValue(); ScopedObject p(scope, o->prototype()); @@ -1224,7 +1224,7 @@ QDateTime QJSValue::toDateTime() const { QV4::Value *val = QJSValuePrivate::getValue(this); if (val) { - QV4::DateObject *date = val->asDateObject(); + QV4::DateObject *date = val->as<DateObject>(); if (date) return date->toQDateTime(); } @@ -1238,7 +1238,7 @@ QDateTime QJSValue::toDateTime() const bool QJSValue::isDate() const { QV4::Value *val = QJSValuePrivate::getValue(this); - return val && val->asDateObject(); + return val && val->as<DateObject>(); } /*! diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h index 93a28a4a5f..08dc184412 100644 --- a/src/qml/jsapi/qjsvalue_p.h +++ b/src/qml/jsapi/qjsvalue_p.h @@ -47,7 +47,7 @@ #include <qjsvalue.h> #include <private/qtqmlglobal_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4string_p.h> #include <private/qv4engine_p.h> #include <private/qv4object_p.h> diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index ef44ca6f4d..51bcc19c6e 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -10,7 +10,6 @@ SOURCES += \ $$PWD/qv4lookup.cpp \ $$PWD/qv4identifier.cpp \ $$PWD/qv4identifiertable.cpp \ - $$PWD/qv4mm.cpp \ $$PWD/qv4managed.cpp \ $$PWD/qv4internalclass.cpp \ $$PWD/qv4sparsearray.cpp \ @@ -57,7 +56,6 @@ HEADERS += \ $$PWD/qv4lookup_p.h \ $$PWD/qv4identifier_p.h \ $$PWD/qv4identifiertable_p.h \ - $$PWD/qv4mm_p.h \ $$PWD/qv4managed_p.h \ $$PWD/qv4internalclass_p.h \ $$PWD/qv4sparsearray_p.h \ @@ -85,6 +83,7 @@ HEADERS += \ $$PWD/qv4serialize_p.h \ $$PWD/qv4script_p.h \ $$PWD/qv4scopedvalue_p.h \ + $$PWD/qv4typedvalue_p.h \ $$PWD/qv4util_p.h \ $$PWD/qv4executableallocator_p.h \ $$PWD/qv4sequenceobject_p.h \ @@ -102,7 +101,7 @@ HEADERS += \ HEADERS += \ $$PWD/qv4runtime_p.h \ - $$PWD/qv4value_inl_p.h \ + $$PWD/qv4value_p.h \ $$PWD/qv4string_p.h \ $$PWD/qv4value_p.h diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 92c77570af..69053f117c 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -33,6 +33,7 @@ #include <qv4argumentsobject_p.h> #include <qv4alloca_p.h> #include <qv4scopedvalue_p.h> +#include "qv4string_p.h" using namespace QV4; @@ -40,7 +41,7 @@ DEFINE_OBJECT_VTABLE(ArgumentsObject); Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context) : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass, - context->d()->engine->objectPrototype.asObject()) + context->d()->engine->objectPrototype()) , context(context->d()) , fullyCreated(false) { @@ -55,10 +56,10 @@ Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context) if (context->d()->strictMode) { Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee)); Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller)); - args->propertyAt(CalleePropertyIndex)->value = v4->thrower; - args->propertyAt(CalleePropertyIndex)->set = v4->thrower; - args->propertyAt(CallerPropertyIndex)->value = v4->thrower; - args->propertyAt(CallerPropertyIndex)->set = v4->thrower; + args->propertyAt(CalleePropertyIndex)->value = v4->thrower(); + args->propertyAt(CalleePropertyIndex)->set = v4->thrower(); + args->propertyAt(CallerPropertyIndex)->value = v4->thrower(); + args->propertyAt(CallerPropertyIndex)->set = v4->thrower(); args->arrayReserve(context->argc()); args->arrayPut(0, context->args(), context->argc()); @@ -144,9 +145,9 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con return result; } -ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue ArgumentsObject::getIndexed(const Managed *m, uint index, bool *hasProperty) { - ArgumentsObject *args = static_cast<ArgumentsObject *>(m); + const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m); if (args->fullyCreated()) return Object::getIndexed(m, index, hasProperty); @@ -199,11 +200,11 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index) DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction); -ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData) +ReturnedValue ArgumentsGetterFunction::call(const Managed *getter, CallData *callData) { - ExecutionEngine *v4 = static_cast<ArgumentsGetterFunction *>(getter)->engine(); + ExecutionEngine *v4 = static_cast<const ArgumentsGetterFunction *>(getter)->engine(); Scope scope(v4); - Scoped<ArgumentsGetterFunction> g(scope, static_cast<ArgumentsGetterFunction *>(getter)); + Scoped<ArgumentsGetterFunction> g(scope, static_cast<const ArgumentsGetterFunction *>(getter)); Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>()); if (!o) return v4->throwTypeError(); @@ -214,11 +215,11 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData) DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction); -ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData) +ReturnedValue ArgumentsSetterFunction::call(const Managed *setter, CallData *callData) { - ExecutionEngine *v4 = static_cast<ArgumentsSetterFunction *>(setter)->engine(); + ExecutionEngine *v4 = static_cast<const ArgumentsSetterFunction *>(setter)->engine(); Scope scope(v4); - Scoped<ArgumentsSetterFunction> s(scope, static_cast<ArgumentsSetterFunction *>(setter)); + Scoped<ArgumentsSetterFunction> s(scope, static_cast<const ArgumentsSetterFunction *>(setter)); Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>()); if (!o) return v4->throwTypeError(); diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 43cd6d1dee..19659429a7 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -59,9 +59,9 @@ struct ArgumentsObject : Object { CallerPropertyIndex = 3 }; ArgumentsObject(QV4::CallContext *context); - CallContext *context; + Pointer<CallContext> context; bool fullyCreated; - MemberData *mappedArguments; + Pointer<MemberData> mappedArguments; }; } @@ -71,7 +71,7 @@ struct ArgumentsGetterFunction: FunctionObject V4_OBJECT2(ArgumentsGetterFunction, FunctionObject) uint index() const { return d()->index; } - static ReturnedValue call(Managed *that, CallData *d); + static ReturnedValue call(const Managed *that, CallData *d); }; inline @@ -86,7 +86,7 @@ struct ArgumentsSetterFunction: FunctionObject V4_OBJECT2(ArgumentsSetterFunction, FunctionObject) uint index() const { return d()->index; } - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; inline @@ -111,7 +111,7 @@ struct ArgumentsObject: Object { } bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs); - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); static void putIndexed(Managed *m, uint index, const Value &value); static bool deleteIndexedProperty(Managed *m, uint index); static PropertyAttributes queryIndexed(const Managed *m, uint index); diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 11664f1194..975f0121b9 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -33,6 +33,7 @@ #include "qv4arraybuffer_p.h" #include "qv4typedarray_p.h" #include "qv4dataview_p.h" +#include "qv4string_p.h" using namespace QV4; @@ -44,9 +45,9 @@ Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope) { } -ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData) +ReturnedValue ArrayBufferCtor::construct(const Managed *m, CallData *callData) { - ExecutionEngine *v4 = static_cast<Object *>(m)->engine(); + ExecutionEngine *v4 = static_cast<const Object *>(m)->engine(); Scope scope(v4); ScopedValue l(scope, callData->argument(0)); @@ -64,7 +65,7 @@ ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData) } -ReturnedValue ArrayBufferCtor::call(Managed *that, CallData *callData) +ReturnedValue ArrayBufferCtor::call(const Managed *that, CallData *callData) { return construct(that, callData); } @@ -83,7 +84,7 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx) Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length) - : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject()) + : Heap::Object(e->emptyClass, e->arrayBufferPrototype()) { data = QTypedArrayData<char>::allocate(length + 1); if (!data) { @@ -96,7 +97,7 @@ Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length) } Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array) - : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject()) + : Heap::Object(e->emptyClass, e->arrayBufferPrototype()) , data(const_cast<QByteArray&>(array).data_ptr()) { data->ref.ref(); diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index fe3150618d..a7f9e92c80 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -61,8 +61,8 @@ struct ArrayBufferCtor: FunctionObject { V4_OBJECT2(ArrayBufferCtor, FunctionObject) - static ReturnedValue construct(Managed *m, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); static ReturnedValue method_isView(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index afcfa00905..627aed0192 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -33,13 +33,14 @@ #include "qv4arraydata_p.h" #include "qv4object_p.h" #include "qv4functionobject_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4runtime_p.h" #include "qv4argumentsobject_p.h" +#include "qv4string_p.h" using namespace QV4; -const QV4::ManagedVTable QV4::ArrayData::static_vtbl = { +const QV4::VTable QV4::ArrayData::static_vtbl = { 0, QV4::ArrayData::IsExecutionContext, QV4::ArrayData::IsString, @@ -230,7 +231,7 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index) bool SimpleArrayData::put(Object *o, uint index, const Value &value) { - Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor()); // ### honour attributes dd->data(index) = value; @@ -244,7 +245,7 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value) bool SimpleArrayData::del(Object *o, uint index) { - Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (index >= dd->len) return true; @@ -266,12 +267,12 @@ void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes att void SimpleArrayData::push_front(Object *o, const Value *values, uint n) { - Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Q_ASSERT(!dd->attrs); if (dd->len + n > dd->alloc) { realloc(o, Heap::ArrayData::Simple, dd->len + n, false); Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple); - dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } dd->offset = (dd->offset - n) % dd->alloc; dd->len += n; @@ -281,7 +282,7 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n) ReturnedValue SimpleArrayData::pop_front(Object *o) { - Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Q_ASSERT(!dd->attrs); if (!dd->len) return Encode::undefined(); @@ -294,7 +295,7 @@ ReturnedValue SimpleArrayData::pop_front(Object *o) uint SimpleArrayData::truncate(Object *o, uint newLen) { - Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (dd->len < newLen) return newLen; @@ -318,10 +319,10 @@ uint SimpleArrayData::length(const Heap::ArrayData *d) bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n) { - Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (index + n > dd->alloc) { reallocate(o, index + n + 1, false); - dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } for (uint i = dd->len; i < index; ++i) dd->data(i) = Primitive::emptyValue(); @@ -369,13 +370,13 @@ Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttr uint SparseArrayData::allocate(Object *o, bool doubleSlot) { Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse); - Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (doubleSlot) { uint *last = &dd->freeList; while (1) { if (*last == UINT_MAX) { reallocate(o, dd->alloc + 2, true); - dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); last = &dd->freeList; Q_ASSERT(*last != UINT_MAX); } @@ -393,7 +394,7 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) } else { if (dd->freeList == UINT_MAX) { reallocate(o, dd->alloc + 1, false); - dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } uint idx = dd->freeList; Q_ASSERT(idx != UINT_MAX); @@ -418,12 +419,12 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value) if (value.isEmpty()) return true; - Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>(); SparseArrayNode *n = s->sparse->insert(index); Q_ASSERT(n->value == UINT_MAX || !s->attrs || !s->attrs[n->value].isAccessor()); if (n->value == UINT_MAX) n->value = allocate(o); - s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + s = o->d()->arrayData.cast<Heap::SparseArrayData>(); s->arrayData[n->value] = value; if (s->attrs) s->attrs[n->value] = Attr_Data; @@ -432,7 +433,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value) bool SparseArrayData::del(Object *o, uint index) { - Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *dd = o->d()->arrayData.cast<Heap::SparseArrayData>(); SparseArrayNode *n = dd->sparse->findNode(index); if (!n) @@ -468,28 +469,28 @@ bool SparseArrayData::del(Object *o, uint index) void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs) { - Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>(); SparseArrayNode *n = d->sparse->insert(index); if (n->value == UINT_MAX) { n->value = allocate(o, attrs.isAccessor()); - d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + d = o->d()->arrayData.cast<Heap::SparseArrayData>(); } else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) { // need to convert the slot free(o->arrayData(), n->value); n->value = allocate(o, attrs.isAccessor()); - d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + d = o->d()->arrayData.cast<Heap::SparseArrayData>(); } d->attrs[n->value] = attrs; } void SparseArrayData::push_front(Object *o, const Value *values, uint n) { - Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>(); Q_ASSERT(!d->attrs); for (int i = n - 1; i >= 0; --i) { uint idx = allocate(o); - d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + d = o->d()->arrayData.cast<Heap::SparseArrayData>(); d->arrayData[idx] = values[i]; d->sparse->push_front(idx); } @@ -497,7 +498,7 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n) ReturnedValue SparseArrayData::pop_front(Object *o) { - Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>(); Q_ASSERT(!d->attrs); uint idx = d->sparse->pop_front(); ReturnedValue v; @@ -512,7 +513,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o) uint SparseArrayData::truncate(Object *o, uint newLen) { - Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>(); SparseArrayNode *begin = d->sparse->lowerBound(newLen); if (begin != d->sparse->end()) { SparseArrayNode *it = d->sparse->end()->previousNode(); @@ -606,11 +607,11 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n) Property *ArrayData::insert(Object *o, uint index, bool isAccessor) { if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) { - Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (index < 0x1000 || index < d->len + (d->len >> 2)) { if (index >= d->alloc) { o->arrayReserve(index + 1); - d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + d = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } if (index >= d->len) { // mark possible hole in the array @@ -623,11 +624,11 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor) } o->initSparseArray(); - Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *s = o->d()->arrayData.cast<Heap::SparseArrayData>(); SparseArrayNode *n = s->sparse->insert(index); if (n->value == UINT_MAX) n->value = SparseArrayData::allocate(o, isAccessor); - s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + s = o->d()->arrayData.cast<Heap::SparseArrayData>(); return reinterpret_cast<Property *>(s->arrayData + n->value); } @@ -737,7 +738,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c if (!arrayData || !arrayData->length()) return; - if (!(comparefn.isUndefined() || comparefn.asObject())) { + if (!(comparefn.isUndefined() || comparefn.as<Object>())) { engine->throwTypeError(); return; } @@ -755,7 +756,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c thisObject->setArrayData(0); ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false); - Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData); + Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>(); SparseArrayNode *n = sparse->sparse()->begin(); uint i = 0; @@ -795,7 +796,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c } } else { - Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData); + Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>(); if (len > d->len) len = d->len; diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 915e862bbb..667827d1e9 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -47,7 +47,7 @@ namespace QV4 { Q_MANAGED_CHECK \ typedef QV4::Heap::DataClass Data; \ static const QV4::ArrayVTable static_vtbl; \ - static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \ + static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \ V4_MANAGED_SIZE_TEST \ const Data *d() const { return static_cast<const Data *>(m); } \ Data *d() { return static_cast<Data *>(m); } @@ -57,7 +57,7 @@ struct ArrayData; struct ArrayVTable { - ManagedVTable managedVTable; + VTable vTable; uint type; Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes); ReturnedValue (*get)(const Heap::ArrayData *d, uint index); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 231eb93dd5..986ceead1c 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -37,6 +37,7 @@ #include "qv4scopedvalue_p.h" #include "qv4argumentsobject_p.h" #include "qv4runtime_p.h" +#include "qv4string_p.h" using namespace QV4; @@ -47,9 +48,9 @@ Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope) { } -ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData) +ReturnedValue ArrayCtor::construct(const Managed *m, CallData *callData) { - ExecutionEngine *v4 = static_cast<ArrayCtor *>(m)->engine(); + ExecutionEngine *v4 = static_cast<const ArrayCtor *>(m)->engine(); Scope scope(v4); ScopedArrayObject a(scope, v4->newArrayObject()); uint len; @@ -72,7 +73,7 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData) return a.asReturnedValue(); } -ReturnedValue ArrayCtor::call(Managed *that, CallData *callData) +ReturnedValue ArrayCtor::call(const Managed *that, CallData *callData) { return construct(that, callData); } @@ -110,7 +111,7 @@ void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx) { - bool isArray = ctx->argc() && ctx->args()[0].asArrayObject(); + bool isArray = ctx->argc() && ctx->args()[0].as<ArrayObject>(); return Encode(isArray); } @@ -194,7 +195,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) QString R; // ### FIXME - if (ArrayObject *a = self->asArrayObject()) { + if (ArrayObject *a = self->as<ArrayObject>()) { ScopedValue e(scope); for (uint i = 0; i < a->getLength(); ++i) { if (i) @@ -619,7 +620,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) return Encode(-1); } else { Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex); - Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(instance->d()->arrayData); + Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>(); if (len > sa->len) len = sa->len; uint idx = fromIndex; diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index 4e67eb2e31..422a0de675 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -53,8 +53,8 @@ struct ArrayCtor: FunctionObject { V4_OBJECT2(ArrayCtor, FunctionObject) - static ReturnedValue construct(Managed *m, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct ArrayPrototype: ArrayObject diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 9c293e783b..a70e45068a 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qv4booleanobject_p.h" +#include "qv4string_p.h" using namespace QV4; @@ -43,14 +44,14 @@ Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope) { } -ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData) +ReturnedValue BooleanCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<BooleanCtor *>(m)->engine()); + Scope scope(static_cast<const BooleanCtor *>(m)->engine()); bool n = callData->argc ? callData->args[0].toBoolean() : false; return Encode(scope.engine->newBooleanObject(n)); } -ReturnedValue BooleanCtor::call(Managed *, CallData *callData) +ReturnedValue BooleanCtor::call(const Managed *, CallData *callData) { bool value = callData->argc ? callData->args[0].toBoolean() : 0; return Encode(value); @@ -73,7 +74,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx) if (ctx->thisObject().isBoolean()) { result = ctx->thisObject().booleanValue(); } else { - BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>(); + const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>(); if (!thisObject) return ctx->engine()->throwTypeError(); result = thisObject->value(); @@ -87,7 +88,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx) if (ctx->thisObject().isBoolean()) return ctx->thisObject().asReturnedValue(); - BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>(); + const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>(); if (!thisObject) return ctx->engine()->throwTypeError(); diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 903261bdce..77b5a74fde 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -53,8 +53,8 @@ struct BooleanCtor: FunctionObject { V4_OBJECT2(BooleanCtor, FunctionObject) - static ReturnedValue construct(Managed *, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct BooleanPrototype: BooleanObject diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 9330f10780..0951015dde 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -36,10 +36,11 @@ #include <qv4context_p.h> #include <qv4object_p.h> #include <qv4objectproto_p.h> -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include <qv4argumentsobject_p.h> #include "qv4function_p.h" #include "qv4errorobject_p.h" +#include "qv4string_p.h" using namespace QV4; @@ -105,7 +106,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) Scope scope(this); // find the right context to create the binding on - ScopedObject activation(scope, d()->engine->globalObject()); + ScopedObject activation(scope, d()->engine->globalObject); ScopedContext ctx(scope, this); while (ctx) { if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { @@ -130,7 +131,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) Heap::GlobalContext::GlobalContext(ExecutionEngine *eng) : Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext) { - global = eng->globalObject()->d(); + global = eng->globalObject->d(); } Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with) @@ -153,7 +154,7 @@ Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exception lookups = parent->lookups; compilationUnit = parent->compilationUnit; - this->exceptionVarName = exceptionVarName; + this->exceptionVarName = exceptionVarName->d(); this->exceptionValue = exceptionValue; } @@ -216,7 +217,7 @@ bool ExecutionContext::deleteProperty(String *name) return withObject->deleteProperty(name); } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) { Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); - if (c->exceptionVarName->isEqualTo(name)) + if (c->exceptionVarName->isEqualTo(name->d())) return false; } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d()); @@ -289,7 +290,7 @@ void ExecutionContext::setProperty(String *name, const Value &value) w->put(name, value); return; } - } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name)) { + } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name->d())) { static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = value; return; } else { @@ -332,7 +333,7 @@ void ExecutionContext::setProperty(String *name, const Value &value) engine()->throwReferenceError(n); return; } - d()->engine->globalObject()->put(name, value); + d()->engine->globalObject->put(name, value); } ReturnedValue ExecutionContext::getProperty(String *name) @@ -362,7 +363,7 @@ ReturnedValue ExecutionContext::getProperty(String *name) else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) { hasCatchScope = true; Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); - if (c->exceptionVarName->isEqualTo(name)) + if (c->exceptionVarName->isEqualTo(name->d())) return c->exceptionValue.asReturnedValue(); } @@ -430,7 +431,7 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object ** else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) { hasCatchScope = true; Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d()); - if (c->exceptionVarName->isEqualTo(name)) + if (c->exceptionVarName->isEqualTo(name->d())) return c->exceptionValue.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 8392dd836d..c35263ba7e 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -45,6 +45,7 @@ struct CompilationUnit; struct Function; } +struct Identifier; struct CallContext; struct CatchContext; struct WithContext; @@ -84,8 +85,8 @@ struct ExecutionContext : Base { CallData *callData; ExecutionEngine *engine; - ExecutionContext *parent; - ExecutionContext *outer; + Pointer<ExecutionContext> parent; + Pointer<ExecutionContext> outer; Lookup *lookups; CompiledData::CompilationUnit *compilationUnit; @@ -104,25 +105,25 @@ struct CallContext : ExecutionContext { } CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function); - FunctionObject *function; + Pointer<FunctionObject> function; Value *locals; - Object *activation; + Pointer<Object> activation; }; struct GlobalContext : ExecutionContext { GlobalContext(ExecutionEngine *engine); - Object *global; + Pointer<Object> global; }; struct CatchContext : ExecutionContext { CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const Value &exceptionValue); - StringValue exceptionVarName; + Pointer<String> exceptionVarName; Value exceptionValue; }; struct WithContext : ExecutionContext { WithContext(ExecutionEngine *engine, QV4::Object *with); - Object *withObject; + Pointer<Object> withObject; }; @@ -160,7 +161,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed static void markObjects(Heap::Base *m, ExecutionEngine *e); - const Value &thisObject() const { + Value &thisObject() const { return d()->callData->thisObject; } int argc() const { diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index 8a66c2cbfc..7d1a13c8fe 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -33,6 +33,7 @@ #include "qv4dataview_p.h" #include "qv4arraybuffer_p.h" +#include "qv4string_p.h" #include "qendian.h" @@ -46,9 +47,9 @@ Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope) { } -ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData) +ReturnedValue DataViewCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<Object *>(m)->engine()); + Scope scope(static_cast<const Object *>(m)->engine()); Scoped<ArrayBuffer> buffer(scope, callData->argument(0)); if (!buffer) return scope.engine->throwTypeError(); @@ -69,14 +70,14 @@ ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData) } -ReturnedValue DataViewCtor::call(Managed *that, CallData *callData) +ReturnedValue DataViewCtor::call(const Managed *that, CallData *callData) { return construct(that, callData); } Heap::DataView::DataView(ExecutionEngine *e) - : Heap::Object(e->emptyClass, e->dataViewPrototype.asObject()), + : Heap::Object(e->emptyClass, e->dataViewPrototype()), buffer(0), byteLength(0), byteOffset(0) diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h index 3f0c1e9e23..e98239396a 100644 --- a/src/qml/jsruntime/qv4dataview_p.h +++ b/src/qml/jsruntime/qv4dataview_p.h @@ -48,7 +48,7 @@ struct DataViewCtor : FunctionObject { struct DataView : Object { DataView(ExecutionEngine *e); - ArrayBuffer *buffer; + Pointer<ArrayBuffer> buffer; uint byteLength; uint byteOffset; }; @@ -59,8 +59,8 @@ struct DataViewCtor: FunctionObject { V4_OBJECT2(DataViewCtor, FunctionObject) - static ReturnedValue construct(Managed *m, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct DataView : Object diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 451ef2486d..87f45c460f 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -36,6 +36,7 @@ #include "qv4objectproto_p.h" #include "qv4scopedvalue_p.h" #include "qv4runtime_p.h" +#include "qv4string_p.h" #include <QtCore/QDebug> #include <QtCore/QDateTime> @@ -628,14 +629,14 @@ static double getLocalTZA() DEFINE_OBJECT_VTABLE(DateObject); Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date) - : Heap::Object(engine->emptyClass, engine->datePrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->datePrototype()) { - value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN()); + this->date = date.isValid() ? date.toMSecsSinceEpoch() : qSNaN(); } QDateTime DateObject::toQDateTime() const { - return ToDateTime(date().asDouble(), Qt::LocalTime); + return ToDateTime(date(), Qt::LocalTime); } DEFINE_OBJECT_VTABLE(DateCtor); @@ -645,9 +646,9 @@ Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope) { } -ReturnedValue DateCtor::construct(Managed *m, CallData *callData) +ReturnedValue DateCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<DateCtor *>(m)->engine()); + Scope scope(static_cast<const DateCtor *>(m)->engine()); double t = 0; if (callData->argc == 0) @@ -655,15 +656,16 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData) else if (callData->argc == 1) { ScopedValue arg(scope, callData->args[0]); - if (DateObject *d = arg->asDateObject()) - arg = d->date(); - else + if (DateObject *d = arg->as<DateObject>()) { + t = d->date(); + } else { arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT); - if (arg->isString()) - t = ParseString(arg->stringValue()->toQString()); - else - t = TimeClip(arg->toNumber()); + if (arg->isString()) + t = ParseString(arg->stringValue()->toQString()); + else + t = TimeClip(arg->toNumber()); + } } else { // d.argc > 1 @@ -683,10 +685,10 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData) return Encode(scope.engine->newDateObject(Primitive::fromDouble(t))); } -ReturnedValue DateCtor::call(Managed *m, CallData *) +ReturnedValue DateCtor::call(const Managed *m, CallData *) { double t = currentTime(); - return static_cast<DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue(); + return static_cast<const DateCtor *>(m)->engine()->newString(ToString(t))->asReturnedValue(); } void DatePrototype::init(ExecutionEngine *engine, Object *ctor) @@ -752,8 +754,8 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor) double DatePrototype::getThisDate(ExecutionContext *ctx) { - if (DateObject *thisObject = ctx->thisObject().asDateObject()) - return thisObject->date().asDouble(); + if (DateObject *thisObject = ctx->thisObject().as<DateObject>()) + return thisObject->date(); else { ctx->engine()->throwTypeError(); return 0; @@ -994,8 +996,8 @@ ReturnedValue DatePrototype::method_setTime(CallContext *ctx) return ctx->engine()->throwTypeError(); double t = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); - self->date().setDouble(TimeClip(t)); - return self->date().asReturnedValue(); + self->setDate(TimeClip(t)); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx) @@ -1005,175 +1007,175 @@ ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx) if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); - self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); - return self->date().asReturnedValue(); + self->setDate(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double ms = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); - self->date().setDouble(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))); - return self->date().asReturnedValue(); + self->setDate(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double sec = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double ms = (ctx->argc() < 2) ? msFromTime(t) : ctx->args()[1].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber(); double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double min = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double sec = (ctx->argc() < 2) ? SecFromTime(t) : ctx->args()[1].toNumber(); double ms = (ctx->argc() < 3) ? msFromTime(t) : ctx->args()[2].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setHours(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber(); double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber(); double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double hour = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double min = (ctx->argc() < 2) ? MinFromTime(t) : ctx->args()[1].toNumber(); double sec = (ctx->argc() < 3) ? SecFromTime(t) : ctx->args()[2].toNumber(); double ms = (ctx->argc() < 4) ? msFromTime(t) : ctx->args()[3].toNumber(); t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setDate(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double date = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setMonth(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double month = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double date = (ctx->argc() < 2) ? DateFromTime(t) : ctx->args()[1].toNumber(); t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setYear(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); if (std::isnan(t)) t = 0; else @@ -1189,49 +1191,49 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx) r = UTC(MakeDate(r, TimeWithinDay(t))); r = TimeClip(r); } - self->date().setDouble(r); - return self->date().asReturnedValue(); + self->setDate(r); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber(); double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber(); t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = LocalTime(self->date().asDouble()); + double t = LocalTime(self->date()); if (std::isnan(t)) t = 0; double year = ctx->argc() ? ctx->args()[0].toNumber() : qSNaN(); double month = (ctx->argc() < 2) ? MonthFromTime(t) : ctx->args()[1].toNumber(); double date = (ctx->argc() < 3) ? DateFromTime(t) : ctx->args()[2].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); - self->date().setDouble(t); - return self->date().asReturnedValue(); + self->setDate(t); + return Encode(self->date()); } ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue(); } @@ -1250,11 +1252,11 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits) ReturnedValue DatePrototype::method_toISOString(CallContext *ctx) { - DateObject *self = ctx->thisObject().asDateObject(); + DateObject *self = ctx->thisObject().as<DateObject>(); if (!self) return ctx->engine()->throwTypeError(); - double t = self->date().asDouble(); + double t = self->date(); if (!std::isfinite(t)) return ctx->engine()->throwRangeError(ctx->thisObject()); @@ -1297,7 +1299,7 @@ ReturnedValue DatePrototype::method_toJSON(CallContext *ctx) ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString"))); ScopedValue v(scope, O->objectValue()->get(s)); - FunctionObject *toIso = v->asFunctionObject(); + FunctionObject *toIso = v->as<FunctionObject>(); if (!toIso) return ctx->engine()->throwTypeError(); diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index dad3689054..133a8d27e8 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -49,18 +49,19 @@ struct DateObject : Object { DateObject(InternalClass *ic, QV4::Object *prototype) : Object(ic, prototype) { - value = Encode(qSNaN()); + date = qSNaN(); } DateObject(QV4::ExecutionEngine *engine, const Value &date) - : Object(engine->emptyClass, engine->datePrototype.asObject()) + : Object(engine->emptyClass, engine->datePrototype()) { - value = date; + this->date = date.toNumber(); } DateObject(QV4::ExecutionEngine *engine, const QDateTime &date); - Value value; + double date; }; + struct DateCtor : FunctionObject { DateCtor(QV4::ExecutionContext *scope); }; @@ -72,19 +73,23 @@ struct DateObject: Object { Q_MANAGED_TYPE(DateObject) - Value date() const { return d()->value; } - Value &date() { return d()->value; } - void setDate(const Value &date) { d()->value = date; } + double date() const { return d()->date; } + void setDate(double date) { d()->date = date; } QDateTime toQDateTime() const; }; +template<> +inline const DateObject *Value::as() const { + return isManaged() && m && m->vtable->type == Managed::Type_DateObject ? static_cast<const DateObject *>(this) : 0; +} + struct DateCtor: FunctionObject { V4_OBJECT2(DateCtor, FunctionObject) - static ReturnedValue construct(Managed *, CallData *callData); - static ReturnedValue call(Managed *that, CallData *); + static ReturnedValue construct(const Managed *, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *); }; struct DatePrototype: DateObject diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 36e7a3558c..cd9e1e3936 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -40,6 +40,7 @@ #include "qv4script_p.h" #include "qv4objectiterator_p.h" #include "qv4identifier_p.h" +#include "qv4string_p.h" #include <iostream> #include <algorithm> @@ -469,7 +470,7 @@ void Debugger::collectThrownValue(Collector *collector) void run() { Scope scope(engine); - ScopedValue v(scope, engine->exceptionValue); + ScopedValue v(scope, *engine->exceptionValue); collector->collect(QStringLiteral("exception"), v); } }; @@ -793,7 +794,7 @@ void Debugger::Collector::collect(const QString &name, const ScopedValue &value) addBoolean(name, value->booleanValue()); break; case Value::Managed_Type: - if (String *s = value->asString()) + if (const String *s = value->as<String>()) addString(name, s->toQString()); else addObject(name, value); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index ba6f5a3b79..eacd4220cd 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -32,7 +32,7 @@ ****************************************************************************/ #include <qv4engine_p.h> #include <qv4context_p.h> -#include <qv4value_inl_p.h> +#include <qv4value_p.h> #include <qv4object_p.h> #include <qv4objectproto_p.h> #include <qv4objectiterator_p.h> @@ -48,7 +48,7 @@ #include <qv4regexp_p.h> #include <qv4variantobject_p.h> #include <qv4runtime_p.h> -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include <qv4argumentsobject_p.h> #include <qv4dateobject_p.h> #include <qv4jsonobject_p.h> @@ -192,6 +192,7 @@ QQmlEngine *ExecutionEngine::qmlEngine() const ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) : current(0) + , hasException(false) , memoryManager(new QV4::MemoryManager(this)) , executableAllocator(new QV4::ExecutableAllocator) , regExpAllocator(new QV4::ExecutableAllocator) @@ -210,9 +211,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) { MemoryManager::GCBlocker gcBlocker(memoryManager); - exceptionValue = Encode::undefined(); - hasException = false; - if (!factory) { #ifdef V4_ENABLE_JIT @@ -236,6 +234,12 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) jsStackBase = (Value *)jsStack->base(); jsStackTop = jsStackBase; + exceptionValue = jsAlloca(1); + globalObject = static_cast<Object *>(jsAlloca(1)); + jsObjects = jsAlloca(NJSObjects); + typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes)); + typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes)); + #ifdef V4_USE_VALGRIND VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit); #endif @@ -246,8 +250,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) if (!recheckCStackLimits()) qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize); - Scope scope(this); - identifierTable = new IdentifierTable(this); classPool = new InternalClassPool; @@ -291,29 +293,29 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) id_buffer = newIdentifier(QStringLiteral("buffer")); id_lastIndex = newIdentifier(QStringLiteral("lastIndex")); - objectPrototype = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0); + jsObjects[ObjectProto] = memoryManager->alloc<ObjectPrototype>(emptyClass, (QV4::Object *)0); arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable); - arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject()); + jsObjects[ArrayProto] = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype()); InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable); argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable); strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - m_globalObject = newObject(); - Q_ASSERT(globalObject()->d()->vtable); + *static_cast<Value *>(globalObject) = newObject(); + Q_ASSERT(globalObject->d()->vtable); initRootContext(); - stringPrototype = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype.asObject()); - numberPrototype = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype.asObject()); - booleanPrototype = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype.asObject()); - datePrototype = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype.asObject()); + jsObjects[StringProto] = memoryManager->alloc<StringPrototype>(emptyClass, objectPrototype()); + jsObjects[NumberProto] = memoryManager->alloc<NumberPrototype>(emptyClass, objectPrototype()); + jsObjects[BooleanProto] = memoryManager->alloc<BooleanPrototype>(emptyClass, objectPrototype()); + jsObjects[DateProto] = memoryManager->alloc<DatePrototype>(emptyClass, objectPrototype()); uint index; InternalClass *functionProtoClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); - functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject()); + jsObjects[FunctionProto] = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype()); 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); @@ -323,131 +325,132 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor); - regExpPrototype = memoryManager->alloc<RegExpPrototype>(this); + jsObjects[RegExpProto] = memoryManager->alloc<RegExpPrototype>(this); regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayIndex); regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayInput); - errorPrototype = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype.asObject()); - evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype.asObject()); - rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype.asObject()); - referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype.asObject()); - syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype.asObject()); - typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype.asObject()); - uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype.asObject()); + jsObjects[ErrorProto] = memoryManager->alloc<ErrorPrototype>(emptyClass, objectPrototype()); + jsObjects[EvalErrorProto] = memoryManager->alloc<EvalErrorPrototype>(emptyClass, errorPrototype()); + jsObjects[RangeErrorProto] = memoryManager->alloc<RangeErrorPrototype>(emptyClass, errorPrototype()); + jsObjects[ReferenceErrorProto] = memoryManager->alloc<ReferenceErrorPrototype>(emptyClass, errorPrototype()); + jsObjects[SyntaxErrorProto] = memoryManager->alloc<SyntaxErrorPrototype>(emptyClass, errorPrototype()); + jsObjects[TypeErrorProto] = memoryManager->alloc<TypeErrorPrototype>(emptyClass, errorPrototype()); + jsObjects[URIErrorProto] = memoryManager->alloc<URIErrorPrototype>(emptyClass, errorPrototype()); - variantPrototype = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype.asObject()); - Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()->d()); + jsObjects[VariantProto] = memoryManager->alloc<VariantPrototype>(emptyClass, objectPrototype()); + Q_ASSERT(variantPrototype()->prototype() == objectPrototype()->d()); - sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject())); + Scope scope(this); + jsObjects[SequenceProto] = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype())); ScopedContext global(scope, rootContext()); - objectCtor = memoryManager->alloc<ObjectCtor>(global); - stringCtor = memoryManager->alloc<StringCtor>(global); - numberCtor = memoryManager->alloc<NumberCtor>(global); - booleanCtor = memoryManager->alloc<BooleanCtor>(global); - arrayCtor = memoryManager->alloc<ArrayCtor>(global); - functionCtor = memoryManager->alloc<FunctionCtor>(global); - dateCtor = memoryManager->alloc<DateCtor>(global); - regExpCtor = memoryManager->alloc<RegExpCtor>(global); - errorCtor = memoryManager->alloc<ErrorCtor>(global); - evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(global); - rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(global); - referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(global); - syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(global); - typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(global); - uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(global); - - static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject()); - static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject()); - static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject()); - static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject()); - static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject()); - static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject()); - static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject()); - static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject()); - static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject()); - static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject()); - static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject()); - static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject()); - static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject()); - static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject()); - static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject()); - - static_cast<VariantPrototype *>(variantPrototype.asObject())->init(); - sequencePrototype.cast<SequencePrototype>()->init(); + jsObjects[Object_Ctor] = memoryManager->alloc<ObjectCtor>(global); + jsObjects[String_Ctor] = memoryManager->alloc<StringCtor>(global); + jsObjects[Number_Ctor] = memoryManager->alloc<NumberCtor>(global); + jsObjects[Boolean_Ctor] = memoryManager->alloc<BooleanCtor>(global); + jsObjects[Array_Ctor] = memoryManager->alloc<ArrayCtor>(global); + jsObjects[Function_Ctor] = memoryManager->alloc<FunctionCtor>(global); + jsObjects[Date_Ctor] = memoryManager->alloc<DateCtor>(global); + jsObjects[RegExp_Ctor] = memoryManager->alloc<RegExpCtor>(global); + jsObjects[Error_Ctor] = memoryManager->alloc<ErrorCtor>(global); + jsObjects[EvalError_Ctor] = memoryManager->alloc<EvalErrorCtor>(global); + jsObjects[RangeError_Ctor] = memoryManager->alloc<RangeErrorCtor>(global); + jsObjects[ReferenceError_Ctor] = memoryManager->alloc<ReferenceErrorCtor>(global); + jsObjects[SyntaxError_Ctor] = memoryManager->alloc<SyntaxErrorCtor>(global); + jsObjects[TypeError_Ctor] = memoryManager->alloc<TypeErrorCtor>(global); + jsObjects[URIError_Ctor] = memoryManager->alloc<URIErrorCtor>(global); + + static_cast<ObjectPrototype *>(objectPrototype())->init(this, objectCtor()); + static_cast<StringPrototype *>(stringPrototype())->init(this, stringCtor()); + static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor()); + static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor()); + static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor()); + static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor()); + static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor()); + static_cast<RegExpPrototype *>(regExpPrototype())->init(this, regExpCtor()); + static_cast<ErrorPrototype *>(errorPrototype())->init(this, errorCtor()); + static_cast<EvalErrorPrototype *>(evalErrorPrototype())->init(this, evalErrorCtor()); + static_cast<RangeErrorPrototype *>(rangeErrorPrototype())->init(this, rangeErrorCtor()); + static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype())->init(this, referenceErrorCtor()); + static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor()); + static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor()); + static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor()); + + static_cast<VariantPrototype *>(variantPrototype())->init(); + sequencePrototype()->cast<SequencePrototype>()->init(); // typed arrays - arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(global); - arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype.asObject()); - static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject()); + jsObjects[ArrayBuffer_Ctor] = memoryManager->alloc<ArrayBufferCtor>(global); + jsObjects[ArrayBufferProto] = memoryManager->alloc<ArrayBufferPrototype>(emptyClass, objectPrototype()); + static_cast<ArrayBufferPrototype *>(arrayBufferPrototype())->init(this, arrayBufferCtor()); - dataViewCtor = memoryManager->alloc<DataViewCtor>(global); - dataViewPrototype = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype.asObject()); - static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject()); + jsObjects[DataView_Ctor] = memoryManager->alloc<DataViewCtor>(global); + jsObjects[DataViewProto] = memoryManager->alloc<DataViewPrototype>(emptyClass, objectPrototype()); + static_cast<DataViewPrototype *>(dataViewPrototype())->init(this, dataViewCtor()); for (int i = 0; i < Heap::TypedArray::NTypes; ++i) { - typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i)); - typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i)); - typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject())); + static_cast<Value &>(typedArrayCtors[i]) = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i)); + static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i)); + typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>())); } // // set up the global object // - rootContext()->global = globalObject()->d(); - rootContext()->callData->thisObject = globalObject(); - Q_ASSERT(globalObject()->d()->vtable); - - globalObject()->defineDefaultProperty(QStringLiteral("Object"), objectCtor); - globalObject()->defineDefaultProperty(QStringLiteral("String"), stringCtor); - globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor); - globalObject()->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor); - globalObject()->defineDefaultProperty(QStringLiteral("Array"), arrayCtor); - globalObject()->defineDefaultProperty(QStringLiteral("Function"), functionCtor); - globalObject()->defineDefaultProperty(QStringLiteral("Date"), dateCtor); - globalObject()->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor); - globalObject()->defineDefaultProperty(QStringLiteral("Error"), errorCtor); - globalObject()->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor); - globalObject()->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor); - globalObject()->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor); - globalObject()->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor); - globalObject()->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor); - globalObject()->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor); - - globalObject()->defineDefaultProperty(QStringLiteral("ArrayBuffer"), arrayBufferCtor); - globalObject()->defineDefaultProperty(QStringLiteral("DataView"), dataViewCtor); + rootContext()->global = globalObject->d(); + rootContext()->callData->thisObject = globalObject; + Q_ASSERT(globalObject->d()->vtable); + + globalObject->defineDefaultProperty(QStringLiteral("Object"), *objectCtor()); + globalObject->defineDefaultProperty(QStringLiteral("String"), *stringCtor()); + globalObject->defineDefaultProperty(QStringLiteral("Number"), *numberCtor()); + globalObject->defineDefaultProperty(QStringLiteral("Boolean"), *booleanCtor()); + globalObject->defineDefaultProperty(QStringLiteral("Array"), *arrayCtor()); + globalObject->defineDefaultProperty(QStringLiteral("Function"), *functionCtor()); + globalObject->defineDefaultProperty(QStringLiteral("Date"), *dateCtor()); + globalObject->defineDefaultProperty(QStringLiteral("RegExp"), *regExpCtor()); + globalObject->defineDefaultProperty(QStringLiteral("Error"), *errorCtor()); + globalObject->defineDefaultProperty(QStringLiteral("EvalError"), *evalErrorCtor()); + globalObject->defineDefaultProperty(QStringLiteral("RangeError"), *rangeErrorCtor()); + globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), *referenceErrorCtor()); + globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), *syntaxErrorCtor()); + globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor()); + globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor()); + + globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor()); + globalObject->defineDefaultProperty(QStringLiteral("DataView"), *dataViewCtor()); ScopedString str(scope); for (int i = 0; i < Heap::TypedArray::NTypes; ++i) - globalObject()->defineDefaultProperty((str = typedArrayCtors[i].asFunctionObject()->name())->toQString(), typedArrayCtors[i]); + globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]); ScopedObject o(scope); - globalObject()->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this))); - globalObject()->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this))); + globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this))); + globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this))); - globalObject()->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue()); - globalObject()->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN())); - globalObject()->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY)); + globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue()); + globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN())); + globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY)); - evalFunction = memoryManager->alloc<EvalFunction>(global); - globalObject()->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction)); + jsObjects[Eval_Function] = memoryManager->alloc<EvalFunction>(global); + globalObject->defineDefaultProperty(QStringLiteral("eval"), *evalFunction()); - globalObject()->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2); - globalObject()->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1); - globalObject()->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1); - globalObject()->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1); - globalObject()->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1); - globalObject()->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1); - globalObject()->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1); - globalObject()->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1); - globalObject()->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1); - globalObject()->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1); + globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2); + globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1); + globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1); + globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1); + globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1); + globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1); + globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1); + globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1); + globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1); + globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1); ScopedString name(scope, newString(QStringLiteral("thrower"))); - thrower = BuiltinFunction::create(global, name, ::throwTypeError); + jsObjects[ThrowerObject] = BuiltinFunction::create(global, name, ::throwTypeError); } ExecutionEngine::~ExecutionEngine() @@ -499,7 +502,7 @@ void ExecutionEngine::initRootContext() r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1); r->d()->callData->tag = QV4::Value::_Integer_Type; r->d()->callData->argc = 0; - r->d()->callData->thisObject = globalObject(); + r->d()->callData->thisObject = globalObject; r->d()->callData->args[0] = Encode::undefined(); m_rootContext = r->d(); @@ -648,7 +651,7 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re) Heap::Object *ExecutionEngine::newErrorObject(const Value &value) { Scope scope(this); - ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype.asObject(), value)); + ScopedObject object(scope, memoryManager->alloc<ErrorObject>(emptyClass, errorPrototype(), value)); return object->d(); } @@ -884,8 +887,6 @@ void ExecutionEngine::markObjects() { identifierTable->mark(this); - globalObject()->mark(this); - for (int i = 0; i < nArgumentsAccessors; ++i) { const Property &pd = argumentsAccessors[i]; if (Heap::FunctionObject *getter = pd.getter()) @@ -941,53 +942,9 @@ void ExecutionEngine::markObjects() id_buffer->mark(this); id_lastIndex->mark(this); - objectCtor.mark(this); - stringCtor.mark(this); - numberCtor.mark(this); - booleanCtor.mark(this); - arrayCtor.mark(this); - functionCtor.mark(this); - dateCtor.mark(this); - regExpCtor.mark(this); - errorCtor.mark(this); - evalErrorCtor.mark(this); - rangeErrorCtor.mark(this); - referenceErrorCtor.mark(this); - syntaxErrorCtor.mark(this); - typeErrorCtor.mark(this); - uRIErrorCtor.mark(this); - arrayBufferCtor.mark(this); - dataViewCtor.mark(this); for (int i = 0; i < Heap::TypedArray::NTypes; ++i) typedArrayCtors[i].mark(this); - objectPrototype.mark(this); - arrayPrototype.mark(this); - stringPrototype.mark(this); - numberPrototype.mark(this); - booleanPrototype.mark(this); - datePrototype.mark(this); - functionPrototype.mark(this); - regExpPrototype.mark(this); - errorPrototype.mark(this); - evalErrorPrototype.mark(this); - rangeErrorPrototype.mark(this); - referenceErrorPrototype.mark(this); - syntaxErrorPrototype.mark(this); - typeErrorPrototype.mark(this); - uRIErrorPrototype.mark(this); - variantPrototype.mark(this); - sequencePrototype.mark(this); - - arrayBufferPrototype.mark(this); - dataViewPrototype.mark(this); - for (int i = 0; i < Heap::TypedArray::NTypes; ++i) - typedArrayPrototype[i].mark(this); - - exceptionValue.mark(this); - - thrower->mark(this); - if (m_qmlExtensions) m_qmlExtensions->markObjects(this); @@ -1015,7 +972,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value) return Encode::undefined(); hasException = true; - exceptionValue = value; + *exceptionValue = value; QV4::Scope scope(this); QV4::Scoped<ErrorObject> error(scope, value); if (!!error) @@ -1036,8 +993,8 @@ ReturnedValue ExecutionEngine::catchException(StackTrace *trace) *trace = exceptionStackTrace; exceptionStackTrace.clear(); hasException = false; - ReturnedValue res = exceptionValue.asReturnedValue(); - exceptionValue = Primitive::emptyValue(); + ReturnedValue res = exceptionValue->asReturnedValue(); + *exceptionValue = Primitive::emptyValue(); return res; } @@ -1193,7 +1150,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int Q_ASSERT (!value.isEmpty()); QV4::Scope scope(e); - if (QV4::VariantObject *v = value.as<QV4::VariantObject>()) + if (const QV4::VariantObject *v = value.as<QV4::VariantObject>()) return v->d()->data; if (typeHint == QVariant::Bool) @@ -1205,10 +1162,10 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int if (typeHint == qMetaTypeId<QJSValue>()) return QVariant::fromValue(QJSValue(e, value.asReturnedValue())); - if (value.asObject()) { + if (value.as<Object>()) { QV4::ScopedObject object(scope, value); if (typeHint == QMetaType::QJsonObject - && !value.asArrayObject() && !value.asFunctionObject()) { + && !value.as<ArrayObject>() && !value.as<FunctionObject>()) { return QVariant::fromValue(QV4::JsonObject::toJsonObject(object)); } else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) { return qVariantFromValue<QObject *>(wrapper->object()); @@ -1224,7 +1181,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return QV4::SequencePrototype::toVariant(object); } - if (value.asArrayObject()) { + if (value.as<ArrayObject>()) { QV4::ScopedArrayObject a(scope, value); if (typeHint == qMetaTypeId<QList<QObject *> >()) { QList<QObject *> list; @@ -1262,11 +1219,11 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return value.asDouble(); if (value.isString()) return value.stringValue()->toQString(); - if (QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>()) + if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>()) return ld->d()->locale; - if (QV4::DateObject *d = value.asDateObject()) + if (const QV4::DateObject *d = value.as<DateObject>()) return d->toQDateTime(); - if (QV4::ArrayBuffer *d = value.as<ArrayBuffer>()) + if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>()) return d->asByteArray(); // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)! @@ -1293,7 +1250,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty object (and no error is thrown). - if (o->asArrayObject()) + if (o->as<ArrayObject>()) return QVariantList(); return QVariantMap(); } @@ -1301,7 +1258,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec QVariant result; - if (o->asArrayObject()) { + if (o->as<ArrayObject>()) { QV4::Scope scope(e); QV4::ScopedArrayObject a(scope, o->asReturnedValue()); QV4::ScopedValue v(scope); @@ -1314,7 +1271,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4Objec } result = list; - } else if (!o->asFunctionObject()) { + } else if (!o->as<FunctionObject>()) { QVariantMap map; QV4::Scope scope(e); QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly); @@ -1625,11 +1582,10 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) return 0; } -void ExecutionEngine::assertObjectBelongsToEngine(const Value &v) +void ExecutionEngine::assertObjectBelongsToEngine(const Heap::Base &baseObject) { - Q_UNUSED(v); - Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this); - Q_UNUSED(v); + Q_ASSERT(!baseObject.vtable->isObject || static_cast<const Heap::Object&>(baseObject).internalClass->engine == this); + Q_UNUSED(baseObject); } // Converts a JS value to a meta-type. @@ -1689,22 +1645,22 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da } return true; case QMetaType::QDateTime: - if (QV4::DateObject *d = value.asDateObject()) { + if (const QV4::DateObject *d = value.as<DateObject>()) { *reinterpret_cast<QDateTime *>(data) = d->toQDateTime(); return true; } break; case QMetaType::QDate: - if (QV4::DateObject *d = value.asDateObject()) { + if (const QV4::DateObject *d = value.as<DateObject>()) { *reinterpret_cast<QDate *>(data) = d->toQDateTime().date(); return true; } break; case QMetaType::QRegExp: - if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) { + if (const QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) { *reinterpret_cast<QRegExp *>(data) = r->toQRegExp(); return true; } break; case QMetaType::QObjectStar: { - QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>(); + const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>(); if (qobjectWrapper || value.isNull()) { *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value); return true; @@ -1783,7 +1739,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da } #endif - // Try to use magic; for compatibility with qscriptvalue_cast. + // Try to use magic; for compatibility with qjsvalue_cast. QByteArray name = QMetaType::typeName(type); if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data))) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index c0c88abaa5..79aafeb268 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -37,6 +37,8 @@ #include "private/qv4isel_p.h" #include "qv4managed_p.h" #include "qv4context_p.h" +#include "qv4typedvalue_p.h" +#include "qv4internalclass_p.h" #include <private/qintrusivelist_p.h> namespace WTF { @@ -106,14 +108,19 @@ public: --jsStackTop; return jsStackTop->heapObject(); } + Value *jsAlloca(int nValues) { + Value *ptr = jsStackTop; + jsStackTop = ptr + nValues; + memset(ptr, 0, nValues*sizeof(Value)); + return ptr; + } IdentifierTable *identifierTable; QV4::Debugging::Debugger *debugger; QV4::Profiling::Profiler *profiler; - Value m_globalObject; - Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); } + Object *globalObject; Function *globalCode; @@ -121,47 +128,92 @@ public: QQmlEngine *qmlEngine() const; QV8Engine *v8Engine; - Value objectCtor; - Value stringCtor; - Value numberCtor; - Value booleanCtor; - Value arrayCtor; - Value functionCtor; - Value dateCtor; - Value regExpCtor; - Value errorCtor; - Value evalErrorCtor; - Value rangeErrorCtor; - Value referenceErrorCtor; - Value syntaxErrorCtor; - Value typeErrorCtor; - Value uRIErrorCtor; - Value arrayBufferCtor; - Value dataViewCtor; - enum { NTypedArrayTypes = 9 }; // avoid header dependency - Value typedArrayCtors[NTypedArrayTypes]; - - Value objectPrototype; - Value arrayPrototype; - Value stringPrototype; - Value numberPrototype; - Value booleanPrototype; - Value datePrototype; - Value functionPrototype; - Value regExpPrototype; - Value errorPrototype; - Value evalErrorPrototype; - Value rangeErrorPrototype; - Value referenceErrorPrototype; - Value syntaxErrorPrototype; - Value typeErrorPrototype; - Value uRIErrorPrototype; - Value variantPrototype; - Value sequencePrototype; - - Value arrayBufferPrototype; - Value dataViewPrototype; - Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here + enum JSObjects { + ObjectProto, + ArrayProto, + StringProto, + NumberProto, + BooleanProto, + DateProto, + FunctionProto, + RegExpProto, + ErrorProto, + EvalErrorProto, + RangeErrorProto, + ReferenceErrorProto, + SyntaxErrorProto, + TypeErrorProto, + URIErrorProto, + VariantProto, + SequenceProto, + ArrayBufferProto, + DataViewProto, + + Object_Ctor, + String_Ctor, + Number_Ctor, + Boolean_Ctor, + Array_Ctor, + Function_Ctor, + Date_Ctor, + RegExp_Ctor, + Error_Ctor, + EvalError_Ctor, + RangeError_Ctor, + ReferenceError_Ctor, + SyntaxError_Ctor, + TypeError_Ctor, + URIError_Ctor, + ArrayBuffer_Ctor, + DataView_Ctor, + + Eval_Function, + ThrowerObject, + NJSObjects + }; + Value *jsObjects; + enum { NTypedArrayTypes = 9 }; // == TypedArray::NValues, avoid header dependency + + FunctionObject *objectCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Object_Ctor); } + FunctionObject *stringCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + String_Ctor); } + FunctionObject *numberCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Number_Ctor); } + FunctionObject *booleanCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Boolean_Ctor); } + FunctionObject *arrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Array_Ctor); } + FunctionObject *functionCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Function_Ctor); } + FunctionObject *dateCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Date_Ctor); } + FunctionObject *regExpCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RegExp_Ctor); } + FunctionObject *errorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Error_Ctor); } + FunctionObject *evalErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + EvalError_Ctor); } + FunctionObject *rangeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + RangeError_Ctor); } + FunctionObject *referenceErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ReferenceError_Ctor); } + FunctionObject *syntaxErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + SyntaxError_Ctor); } + FunctionObject *typeErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + TypeError_Ctor); } + FunctionObject *uRIErrorCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + URIError_Ctor); } + FunctionObject *arrayBufferCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + ArrayBuffer_Ctor); } + FunctionObject *dataViewCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + DataView_Ctor); } + FunctionObject *typedArrayCtors; + + Object *objectPrototype() const { return reinterpret_cast<Object *>(jsObjects + ObjectProto); } + Object *arrayPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayProto); } + Object *stringPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringProto); } + Object *numberPrototype() const { return reinterpret_cast<Object *>(jsObjects + NumberProto); } + Object *booleanPrototype() const { return reinterpret_cast<Object *>(jsObjects + BooleanProto); } + Object *datePrototype() const { return reinterpret_cast<Object *>(jsObjects + DateProto); } + Object *functionPrototype() const { return reinterpret_cast<Object *>(jsObjects + FunctionProto); } + Object *regExpPrototype() const { return reinterpret_cast<Object *>(jsObjects + RegExpProto); } + Object *errorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ErrorProto); } + Object *evalErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + EvalErrorProto); } + Object *rangeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + RangeErrorProto); } + Object *referenceErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ReferenceErrorProto); } + Object *syntaxErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + SyntaxErrorProto); } + Object *typeErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + TypeErrorProto); } + Object *uRIErrorPrototype() const { return reinterpret_cast<Object *>(jsObjects + URIErrorProto); } + Object *variantPrototype() const { return reinterpret_cast<Object *>(jsObjects + VariantProto); } + Object *sequencePrototype() const { return reinterpret_cast<Object *>(jsObjects + SequenceProto); } + + Object *arrayBufferPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayBufferProto); } + Object *dataViewPrototype() const { return reinterpret_cast<Object *>(jsObjects + DataViewProto); } + Object *typedArrayPrototype; InternalClassPool *classPool; InternalClass *emptyClass; @@ -177,8 +229,8 @@ public: InternalClass *argumentsObjectClass; InternalClass *strictArgumentsObjectClass; - Heap::EvalFunction *evalFunction; - Heap::FunctionObject *thrower; + EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); } + FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); } Property *argumentsAccessors; int nArgumentsAccessors; @@ -310,7 +362,7 @@ public: bool recheckCStackLimits(); // Exception handling - Value exceptionValue; + Value *exceptionValue; StackTrace exceptionStackTrace; ReturnedValue throwError(const Value &value); @@ -340,7 +392,7 @@ public: bool metaTypeFromJS(const Value &value, int type, void *data); QV4::ReturnedValue metaTypeToJS(int type, const void *data); - void assertObjectBelongsToEngine(const Value &v); + void assertObjectBelongsToEngine(const Heap::Base &baseObject); private: QmlExtensions *m_qmlExtensions; @@ -376,29 +428,26 @@ Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t) } -// ### Remove me inline -void Managed::mark(QV4::ExecutionEngine *engine) +void Heap::Base::mark(QV4::ExecutionEngine *engine) { Q_ASSERT(inUse()); - if (markBit()) + if (isMarked()) return; #ifndef QT_NO_DEBUG engine->assertObjectBelongsToEngine(*this); #endif - d()->setMarkBit(); - engine->pushForGC(d()); + setMarkBit(); + engine->pushForGC(this); } - -inline -void Heap::Base::mark(QV4::ExecutionEngine *engine) +inline void Value::mark(ExecutionEngine *e) { - Q_ASSERT(inUse()); - if (isMarked()) + if (!val) return; - setMarkBit(); - engine->pushForGC(this); + Managed *m = as<Managed>(); + if (m) + m->d()->mark(e); } diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 9034dee6a0..2f9e09205a 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -33,11 +33,14 @@ #include "qv4errorobject_p.h" -#include "qv4mm_p.h" +#include <QtCore/qnumeric.h> +#include <QtCore/qmath.h> #include <QtCore/QDateTime> #include <QtCore/QStringList> #include <QtCore/QDebug> +#include "qv4string_p.h" +#include <private/qv4mm_p.h> #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> #include <private/qqmljsparser_p.h> @@ -179,57 +182,57 @@ DEFINE_OBJECT_VTABLE(ErrorObject); DEFINE_OBJECT_VTABLE(SyntaxErrorObject); Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const Value &msg) - : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, SyntaxError) + : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, SyntaxError) { } Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError) + : Heap::ErrorObject(engine->emptyClass, engine->syntaxErrorPrototype(), msg, fileName, lineNumber, columnNumber, SyntaxError) { } Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const Value &message) - : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype.asObject(), message, EvalError) + : Heap::ErrorObject(engine->emptyClass, engine->evalErrorPrototype(), message, EvalError) { } Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const Value &message) - : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError) + : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError) { } Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message) - : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype.asObject(), message, RangeError) + : Heap::ErrorObject(engine->emptyClass, engine->rangeErrorPrototype(), message, RangeError) { } Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const Value &message) - : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError) + : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError) { } Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message) - : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError) + : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), message, ReferenceError) { } Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, ReferenceError) + : Heap::ErrorObject(engine->emptyClass, engine->referenceErrorPrototype(), msg, fileName, lineNumber, columnNumber, ReferenceError) { } Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const Value &message) - : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError) + : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError) { } Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message) - : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype.asObject(), message, TypeError) + : Heap::ErrorObject(engine->emptyClass, engine->typeErrorPrototype(), message, TypeError) { } Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const Value &message) - : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype.asObject(), message, URIError) + : Heap::ErrorObject(engine->emptyClass, engine->uRIErrorPrototype(), message, URIError) { } @@ -251,16 +254,16 @@ Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name) { } -ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue ErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<ErrorCtor *>(m)->engine()); + Scope scope(static_cast<const ErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return Encode(scope.engine->newErrorObject(v)); } -ReturnedValue ErrorCtor::call(Managed *that, CallData *callData) +ReturnedValue ErrorCtor::call(const Managed *that, CallData *callData) { - return static_cast<Object *>(that)->construct(callData); + return static_cast<const Object *>(that)->construct(callData); } Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope) @@ -268,9 +271,9 @@ Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope) { } -ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue EvalErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<EvalErrorCtor *>(m)->engine()); + Scope scope(static_cast<const EvalErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return (scope.engine->memoryManager->alloc<EvalErrorObject>(scope.engine, v))->asReturnedValue(); } @@ -280,9 +283,9 @@ Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope) { } -ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue RangeErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<RangeErrorCtor *>(m)->engine()); + Scope scope(static_cast<const RangeErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return (scope.engine->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue(); } @@ -292,9 +295,9 @@ Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope) { } -ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue ReferenceErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<ReferenceErrorCtor *>(m)->engine()); + Scope scope(static_cast<const ReferenceErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return (scope.engine->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue(); } @@ -304,9 +307,9 @@ Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope) { } -ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue SyntaxErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<SyntaxErrorCtor *>(m)->engine()); + Scope scope(static_cast<const SyntaxErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return (scope.engine->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue(); } @@ -316,9 +319,9 @@ Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope) { } -ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue TypeErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<TypeErrorCtor *>(m)->engine()); + Scope scope(static_cast<const TypeErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return (scope.engine->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue(); } @@ -328,9 +331,9 @@ Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope) { } -ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData) +ReturnedValue URIErrorCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<URIErrorCtor *>(m)->engine()); + Scope scope(static_cast<const URIErrorCtor *>(m)->engine()); ScopedValue v(scope, callData->argument(0)); return (scope.engine->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue(); } @@ -351,7 +354,7 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); - Object *o = ctx->thisObject().asObject(); + Object *o = ctx->thisObject().as<Object>(); if (!o) return ctx->engine()->throwTypeError(); diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 071f5b8c9a..da2c978e5f 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -62,7 +62,7 @@ struct ErrorObject : Object { ErrorType errorType; StackTrace stackTrace; - String *stack; + Pointer<String> stack; }; struct EvalErrorObject : ErrorObject { @@ -141,8 +141,8 @@ struct ErrorObject: Object { }; template<> -inline ErrorObject *value_cast(const Value &v) { - return v.asErrorObject(); +inline const ErrorObject *Value::as() const { + return isManaged() && m && m->vtable->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : 0; } struct EvalErrorObject: ErrorObject { @@ -183,50 +183,50 @@ struct ErrorCtor: FunctionObject { V4_OBJECT2(ErrorCtor, FunctionObject) - static ReturnedValue construct(Managed *, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct EvalErrorCtor: ErrorCtor { V4_OBJECT2(EvalErrorCtor, ErrorCtor) - static ReturnedValue construct(Managed *m, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); }; struct RangeErrorCtor: ErrorCtor { V4_OBJECT2(RangeErrorCtor, ErrorCtor) - static ReturnedValue construct(Managed *m, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); }; struct ReferenceErrorCtor: ErrorCtor { V4_OBJECT2(ReferenceErrorCtor, ErrorCtor) - static ReturnedValue construct(Managed *m, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); }; struct SyntaxErrorCtor: ErrorCtor { V4_OBJECT2(SyntaxErrorCtor, ErrorCtor) - static ReturnedValue construct(Managed *m, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); }; struct TypeErrorCtor: ErrorCtor { V4_OBJECT2(TypeErrorCtor, ErrorCtor) - static ReturnedValue construct(Managed *m, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); }; struct URIErrorCtor: ErrorCtor { V4_OBJECT2(URIErrorCtor, ErrorCtor) - static ReturnedValue construct(Managed *m, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); }; diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index efe6c7c226..a18a2d4919 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -34,10 +34,10 @@ #include "qv4function_p.h" #include "qv4managed_p.h" #include "qv4string_p.h" -#include "qv4value_inl_p.h" +#include "qv4value_p.h" #include "qv4engine_p.h" #include "qv4lookup_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 0a12d013ac..27b7448102 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -37,7 +37,7 @@ #include "qv4objectproto_p.h" #include "qv4stringobject_p.h" #include "qv4function_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4arrayobject_p.h" #include "qv4scopedvalue_p.h" @@ -63,7 +63,7 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) - : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype()) , scope(scope->d()) , function(Q_NULLPTR) { @@ -73,7 +73,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String * } Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto) - : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype()) , scope(scope->d()) , function(Q_NULLPTR) { @@ -84,7 +84,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun } Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto) - : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype()) , scope(scope->d()) , function(Q_NULLPTR) { @@ -95,7 +95,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString } Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) - : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject()) + : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype()) , scope(scope) , function(Q_NULLPTR) { @@ -106,7 +106,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam } Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name) - : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) + : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype()) , scope(scope->d()) , function(Q_NULLPTR) { @@ -117,7 +117,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne } Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name) - : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject()) + : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype()) , scope(scope) , function(Q_NULLPTR) { @@ -152,7 +152,7 @@ void FunctionObject::init(String *n, bool createProto) ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype); if (createProto) { - ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype.asObject())); + ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype())); proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor); proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue(); memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue(); @@ -164,7 +164,7 @@ void FunctionObject::init(String *n, bool createProto) defineReadonlyProperty(s.engine->id_name, v); } -ReturnedValue FunctionObject::name() +ReturnedValue FunctionObject::name() const { return get(scope()->engine->id_name); } @@ -177,13 +177,12 @@ ReturnedValue FunctionObject::newInstance() return construct(callData); } -ReturnedValue FunctionObject::construct(Managed *that, CallData *) +ReturnedValue FunctionObject::construct(const Managed *that, CallData *) { - static_cast<FunctionObject *>(that)->internalClass()->engine->throwTypeError(); - return Encode::undefined(); + return static_cast<const FunctionObject *>(that)->engine()->throwTypeError(); } -ReturnedValue FunctionObject::call(Managed *, CallData *) +ReturnedValue FunctionObject::call(const Managed *, CallData *) { return Encode::undefined(); } @@ -237,10 +236,10 @@ Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope) } // 15.3.2 -ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) +ReturnedValue FunctionCtor::construct(const Managed *that, CallData *callData) { - Scope scope(static_cast<Object *>(that)->engine()); - Scoped<FunctionCtor> f(scope, static_cast<FunctionCtor *>(that)); + Scope scope(static_cast<const Object *>(that)->engine()); + Scoped<FunctionCtor> f(scope, static_cast<const FunctionCtor *>(that)); ScopedContext ctx(scope, scope.engine->currentContext()); QString arguments; QString body; @@ -287,7 +286,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) } // 15.3.1: This is equivalent to new Function(...) -ReturnedValue FunctionCtor::call(Managed *that, CallData *callData) +ReturnedValue FunctionCtor::call(const Managed *that, CallData *callData) { return construct(that, callData); } @@ -318,7 +317,7 @@ void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) ReturnedValue FunctionPrototype::method_toString(CallContext *ctx) { - FunctionObject *fun = ctx->thisObject().asFunctionObject(); + FunctionObject *fun = ctx->thisObject().as<FunctionObject>(); if (!fun) return ctx->engine()->throwTypeError(); @@ -328,7 +327,7 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx) ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) { Scope scope(ctx); - ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject()); + ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>()); if (!o) return ctx->engine()->throwTypeError(); @@ -370,7 +369,7 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx) { Scope scope(ctx); - ScopedFunctionObject o(scope, ctx->thisObject().asFunctionObject()); + ScopedFunctionObject o(scope, ctx->thisObject().as<FunctionObject>()); if (!o) return ctx->engine()->throwTypeError(); @@ -409,15 +408,15 @@ Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *fun { } -ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) +ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData) { - ExecutionEngine *v4 = static_cast<Object *>(that)->engine(); + ExecutionEngine *v4 = static_cast<const Object *>(that)->engine(); if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); Scope scope(v4); - Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that)); + Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that)); InternalClass *ic = scope.engine->emptyClass; ScopedObject proto(scope, f->protoForConstructor()); @@ -441,15 +440,15 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) return obj.asReturnedValue(); } -ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) +ReturnedValue ScriptFunction::call(const Managed *that, CallData *callData) { - ExecutionEngine *v4 = static_cast<Object *>(that)->engine(); + ExecutionEngine *v4 = static_cast<const Object *>(that)->engine(); if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); Scope scope(v4); - Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that)); + Scoped<ScriptFunction> f(scope, static_cast<const ScriptFunction *>(that)); ScopedContext context(scope, v4->currentContext()); Scoped<CallContext> ctx(scope, context->newCallContext(f, callData)); @@ -466,7 +465,7 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) DEFINE_OBJECT_VTABLE(SimpleScriptFunction); Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto) - : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype.asObject()) + : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype()) { this->scope = scope->d(); @@ -490,22 +489,22 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F if (scope->d()->strictMode) { ScopedProperty pd(s); - pd->value = s.engine->thrower; - pd->set = s.engine->thrower; + pd->value = s.engine->thrower(); + pd->set = s.engine->thrower(); f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } } -ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) +ReturnedValue SimpleScriptFunction::construct(const Managed *that, CallData *callData) { - ExecutionEngine *v4 = static_cast<Object *>(that)->engine(); + ExecutionEngine *v4 = static_cast<const Object *>(that)->engine(); if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); Scope scope(v4); - Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that)); + Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); InternalClass *ic = scope.engine->emptyClass; ScopedObject proto(scope, f->protoForConstructor()); @@ -536,15 +535,15 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) return result.asReturnedValue(); } -ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) +ReturnedValue SimpleScriptFunction::call(const Managed *that, CallData *callData) { - ExecutionEngine *v4 = static_cast<SimpleScriptFunction *>(that)->internalClass()->engine; + ExecutionEngine *v4 = static_cast<const SimpleScriptFunction *>(that)->internalClass()->engine; if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); Scope scope(v4); - Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that)); + Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); ExecutionContextSaver ctxSaver(scope, v4->currentContext()); @@ -575,7 +574,7 @@ Heap::Object *SimpleScriptFunction::protoForConstructor() ScopedObject p(scope, protoProperty()); if (p) return p->d(); - return scope.engine->objectPrototype.asObject()->d(); + return scope.engine->objectPrototype()->d(); } @@ -588,14 +587,14 @@ Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String { } -ReturnedValue BuiltinFunction::construct(Managed *f, CallData *) +ReturnedValue BuiltinFunction::construct(const Managed *f, CallData *) { - return static_cast<BuiltinFunction *>(f)->internalClass()->engine->throwTypeError(); + return static_cast<const BuiltinFunction *>(f)->internalClass()->engine->throwTypeError(); } -ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData) +ReturnedValue BuiltinFunction::call(const Managed *that, CallData *callData) { - BuiltinFunction *f = static_cast<BuiltinFunction *>(that); + const BuiltinFunction *f = static_cast<const BuiltinFunction *>(that); ExecutionEngine *v4 = f->internalClass()->engine; if (v4->hasException) return Encode::undefined(); @@ -614,9 +613,9 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData) return f->d()->code(sctx); } -ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData) +ReturnedValue IndexedBuiltinFunction::call(const Managed *that, CallData *callData) { - IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that); + const IndexedBuiltinFunction *f = static_cast<const IndexedBuiltinFunction *>(that); ExecutionEngine *v4 = f->internalClass()->engine; if (v4->hasException) return Encode::undefined(); @@ -659,15 +658,15 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len)); ScopedProperty pd(s); - pd->value = s.engine->thrower; - pd->set = s.engine->thrower; + pd->value = s.engine->thrower(); + pd->set = s.engine->thrower(); f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } -ReturnedValue BoundFunction::call(Managed *that, CallData *dd) +ReturnedValue BoundFunction::call(const Managed *that, CallData *dd) { - BoundFunction *f = static_cast<BoundFunction *>(that); + const BoundFunction *f = static_cast<const BoundFunction *>(that); Scope scope(f->engine()); if (scope.hasException()) return Encode::undefined(); @@ -685,9 +684,9 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd) return t->call(callData); } -ReturnedValue BoundFunction::construct(Managed *that, CallData *dd) +ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd) { - BoundFunction *f = static_cast<BoundFunction *>(that); + const BoundFunction *f = static_cast<const BoundFunction *>(that); Scope scope(f->engine()); if (scope.hasException()) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 252ff40a1a..67a929554b 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -36,7 +36,7 @@ #include "qv4object_p.h" #include "qv4function_p.h" #include "qv4context_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> QT_BEGIN_NAMESPACE @@ -65,7 +65,7 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } bool needsActivation() const { return function ? function->needsActivation() : false; } - ExecutionContext *scope; + Pointer<ExecutionContext> scope; Function *function; }; @@ -102,9 +102,9 @@ struct ScriptFunction : SimpleScriptFunction { struct BoundFunction : FunctionObject { BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); - FunctionObject *target; + Pointer<FunctionObject> target; Value boundThis; - MemberData *boundArgs; + Pointer<MemberData> boundArgs; }; } @@ -117,10 +117,10 @@ struct Q_QML_EXPORT FunctionObject: Object { Q_MANAGED_TYPE(FunctionObject) V4_NEEDS_DESTROY - Heap::ExecutionContext *scope() { return d()->scope; } - Function *function() { return d()->function; } + Heap::ExecutionContext *scope() const { return d()->scope; } + Function *function() const { return d()->function; } - ReturnedValue name(); + ReturnedValue name() const; unsigned int formalParameterCount() { return d()->formalParameterCount(); } unsigned int varCount() { return d()->varCount(); } @@ -130,12 +130,8 @@ struct Q_QML_EXPORT FunctionObject: Object { using Object::construct; using Object::call; - static ReturnedValue construct(Managed *that, CallData *); - static ReturnedValue call(Managed *that, CallData *d); - - static FunctionObject *cast(const Value &v) { - return v.asFunctionObject(); - } + static ReturnedValue construct(const Managed *that, CallData *); + static ReturnedValue call(const Managed *that, CallData *d); static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true); @@ -152,16 +148,17 @@ struct Q_QML_EXPORT FunctionObject: Object { }; template<> -inline FunctionObject *value_cast(const Value &v) { - return v.asFunctionObject(); +inline const FunctionObject *Value::as() const { + return isManaged() && m && m->vtable->isFunctionObject ? reinterpret_cast<const FunctionObject *>(this) : 0; } + struct FunctionCtor: FunctionObject { V4_OBJECT2(FunctionCtor, FunctionObject) - static ReturnedValue construct(Managed *that, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *that, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct FunctionPrototype: FunctionObject @@ -184,20 +181,20 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject { return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code); } - static ReturnedValue construct(Managed *, CallData *); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *, CallData *); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct IndexedBuiltinFunction: FunctionObject { V4_OBJECT2(IndexedBuiltinFunction, FunctionObject) - static ReturnedValue construct(Managed *m, CallData *) + static ReturnedValue construct(const Managed *m, CallData *) { - return static_cast<IndexedBuiltinFunction *>(m)->engine()->throwTypeError(); + return static_cast<const IndexedBuiltinFunction *>(m)->engine()->throwTypeError(); } - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, @@ -212,8 +209,8 @@ Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scop struct SimpleScriptFunction: FunctionObject { V4_OBJECT2(SimpleScriptFunction, FunctionObject) - static ReturnedValue construct(Managed *, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); Heap::Object *protoForConstructor(); }; @@ -221,8 +218,8 @@ struct SimpleScriptFunction: FunctionObject { struct ScriptFunction: SimpleScriptFunction { V4_OBJECT2(ScriptFunction, FunctionObject) - static ReturnedValue construct(Managed *, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; @@ -234,12 +231,12 @@ struct BoundFunction: FunctionObject { return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs); } - Heap::FunctionObject *target() { return d()->target; } + Heap::FunctionObject *target() const { return d()->target; } Value boundThis() const { return d()->boundThis; } Heap::MemberData *boundArgs() const { return d()->boundArgs; } - static ReturnedValue construct(Managed *, CallData *d); - static ReturnedValue call(Managed *that, CallData *dd); + static ReturnedValue construct(const Managed *, CallData *d); + static ReturnedValue call(const Managed *that, CallData *dd); static void markObjects(Heap::Base *that, ExecutionEngine *e); }; diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 4b08194b60..9f37ede2c1 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -88,6 +88,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } #define V4_ENABLE_JIT #endif +#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX) +#define V4_ENABLE_JIT #endif // Black list some platforms @@ -168,7 +170,7 @@ struct Property; struct Value; struct Lookup; struct ArrayData; -struct ManagedVTable; +struct VTable; struct BooleanObject; struct NumberObject; diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 8e33cec57f..9b85067d26 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -32,13 +32,14 @@ ****************************************************************************/ #include "qv4globalobject_p.h" -#include "qv4mm_p.h" -#include "qv4value_inl_p.h" +#include <private/qv4mm_p.h> +#include "qv4value_p.h" #include "qv4context_p.h" #include "qv4function_p.h" #include "qv4debugging_p.h" #include "qv4script_p.h" #include "qv4scopedvalue_p.h" +#include "qv4string_p.h" #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -346,7 +347,7 @@ Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope) f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1)); } -ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) +ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const { if (callData->argc < 1) return Encode::undefined(); @@ -399,10 +400,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) } -ReturnedValue EvalFunction::call(Managed *that, CallData *callData) +ReturnedValue EvalFunction::call(const Managed *that, CallData *callData) { // indirect call - return static_cast<EvalFunction *>(that)->evalCall(callData, false); + return static_cast<const EvalFunction *>(that)->evalCall(callData, false); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 74de233b47..ba1d5d2e0b 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -52,10 +52,10 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject { V4_OBJECT2(EvalFunction, FunctionObject) - ReturnedValue evalCall(CallData *callData, bool directCall); + ReturnedValue evalCall(CallData *callData, bool directCall) const; using Object::construct; - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct GlobalFunctions diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index e4bd460966..9bbcc0e21b 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -54,7 +54,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContex : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context) { m_qmlglobal.set(engine, qmlglobal); - if (callback.asFunctionObject()) + if (callback.as<QV4::FunctionObject>()) m_callbackFunction.set(engine, callback); m_resultObject.set(v4, resultValue(v4)); @@ -94,14 +94,14 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status) { if (!callback.isObject()) return; - QV4::ExecutionEngine *v4 = callback.asObject()->engine(); + QV4::ExecutionEngine *v4 = callback.as<QV4::Object>()->engine(); QV4::Scope scope(v4); QV4::ScopedFunctionObject f(scope, callback); if (!f) return; QV4::ScopedCallData callData(scope, 1); - callData->thisObject = v4->globalObject()->asReturnedValue(); + callData->thisObject = v4->globalObject->asReturnedValue(); callData->args[0] = status; f->call(callData); if (scope.hasException()) @@ -184,7 +184,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow())); QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue()); - if (ctx->argc() >= 2 && ctx->args()[1].asFunctionObject()) + if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>()) callbackFunction = ctx->args()[1]; QString localFile = QQmlFile::urlToLocalFileOrQrc(url); @@ -224,7 +224,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) QV4::ScopedValue ex(scope, scope.engine->catchException()); result = resultValue(scope.engine, Exception); QV4::ScopedString exception(scope, scope.engine->newString(QStringLiteral("exception"))); - result->asObject()->put(exception, ex); + result->as<QV4::Object>()->put(exception, ex); } else { result = resultValue(scope.engine, Ok); } diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h index 5dc94e8555..5ef4442b03 100644 --- a/src/qml/jsruntime/qv4include_p.h +++ b/src/qml/jsruntime/qv4include_p.h @@ -50,7 +50,7 @@ #include <private/qqmlcontext_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4context_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 3289058cb7..80590fe72e 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -46,7 +46,7 @@ struct String; struct ExecutionEngine; struct Object; struct Identifier; -struct ManagedVTable; +struct VTable; struct PropertyHashData; struct PropertyHash diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index e7905974df..95d08d7a10 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -38,8 +38,8 @@ #include <qv4objectiterator_p.h> #include <qv4scopedvalue_p.h> #include <qv4runtime_p.h> +#include "qv4string_p.h" -#include <qjsondocument.h> #include <qstack.h> #include <qstringlist.h> @@ -62,33 +62,6 @@ static int indent = 0; DEFINE_OBJECT_VTABLE(JsonObject); -class JsonParser -{ -public: - JsonParser(ExecutionEngine *engine, const QChar *json, int length); - - ReturnedValue parse(QJsonParseError *error); - -private: - inline bool eatSpace(); - inline QChar nextToken(); - - ReturnedValue parseObject(); - ReturnedValue parseArray(); - bool parseMember(Object *o); - bool parseString(QString *string); - bool parseValue(Value *val); - bool parseNumber(Value *val); - - ExecutionEngine *engine; - const QChar *head; - const QChar *json; - const QChar *end; - - int nestingLevel; - QJsonParseError::ParseError lastError; -}; - static const int nestingLimit = 1024; @@ -728,11 +701,11 @@ QString Stringify::Str(const QString &key, const Value &v) o = value->asReturnedValue(); if (o) { - if (NumberObject *n = o->asNumberObject()) + if (NumberObject *n = o->as<NumberObject>()) value = Encode(n->value()); - else if (StringObject *so = o->asStringObject()) + else if (StringObject *so = o->as<StringObject>()) value = so->d()->value; - else if (BooleanObject *b =o->asBooleanObject()) + else if (BooleanObject *b = o->as<BooleanObject>()) value = Encode(b->value()); } @@ -750,8 +723,8 @@ QString Stringify::Str(const QString &key, const Value &v) o = value->asReturnedValue(); if (o) { - if (!o->asFunctionObject()) { - if (o->asArrayObject()) { + if (!o->as<FunctionObject>()) { + if (o->as<ArrayObject>()) { return JA(static_cast<ArrayObject *>(o.getPointer())); } else { return JO(o); @@ -879,7 +852,7 @@ QString Stringify::JA(ArrayObject *a) Heap::JsonObject::JsonObject(ExecutionEngine *e) - : Heap::Object(e->emptyClass, e->objectPrototype.asObject()) + : Heap::Object(e->emptyClass, e->objectPrototype()) { Scope scope(e); ScopedObject o(scope, this); @@ -915,13 +888,13 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) ScopedObject o(scope, ctx->argument(1)); if (o) { - stringify.replacerFunction = o->asFunctionObject(); + stringify.replacerFunction = o->as<FunctionObject>(); if (o->isArrayObject()) { uint arrayLen = o->getLength(); ScopedValue v(scope); for (uint i = 0; i < arrayLen; ++i) { v = o->getIndexed(i); - if (v->asNumberObject() || v->asStringObject() || v->isNumber()) + if (v->as<NumberObject>() || v->as<StringObject>() || v->isNumber()) v = RuntimeHelpers::toString(scope.engine, v); if (v->isString()) { String *s = v->stringValue(); @@ -933,9 +906,9 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) } ScopedValue s(scope, ctx->argument(2)); - if (NumberObject *n = s->asNumberObject()) + if (NumberObject *n = s->as<NumberObject>()) s = Encode(n->value()); - else if (StringObject *so = s->asStringObject()) + else if (StringObject *so = s->as<StringObject>()) s = so->d()->value; if (s->isNumber()) { @@ -986,7 +959,7 @@ QJsonValue JsonObject::toJsonValue(const Value &value, V4ObjectSet &visitedObjec return QJsonValue(value.toQString()); Q_ASSERT(value.isObject()); - Scope scope(value.asObject()->engine()); + Scope scope(value.as<Object>()->engine()); ScopedArrayObject a(scope, value); if (a) return toJsonArray(a, visitedObjects); @@ -1012,7 +985,7 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects) { QJsonObject result; - if (!o || o->asFunctionObject()) + if (!o || o->as<FunctionObject>()) return result; Scope scope(o->engine()); @@ -1035,7 +1008,7 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects) break; QString key = name->toQStringNoThrow(); - if (!val->asFunctionObject()) + if (!val->as<FunctionObject>()) result.insert(key, toJsonValue(val, visitedObjects)); } @@ -1078,7 +1051,7 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects) quint32 length = a->getLength(); for (quint32 i = 0; i < length; ++i) { v = a->getIndexed(i); - if (v->asFunctionObject()) + if (v->as<FunctionObject>()) v = Encode::null(); result.append(toJsonValue(v, visitedObjects)); } diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index 81a783ee92..b8b9cf3093 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -37,6 +37,7 @@ #include <qjsonarray.h> #include <qjsonobject.h> #include <qjsonvalue.h> +#include <qjsondocument.h> QT_BEGIN_NAMESPACE @@ -79,6 +80,33 @@ private: }; +class JsonParser +{ +public: + JsonParser(ExecutionEngine *engine, const QChar *json, int length); + + ReturnedValue parse(QJsonParseError *error); + +private: + inline bool eatSpace(); + inline QChar nextToken(); + + ReturnedValue parseObject(); + ReturnedValue parseArray(); + bool parseMember(Object *o); + bool parseString(QString *string); + bool parseValue(Value *val); + bool parseNumber(Value *val); + + ExecutionEngine *engine; + const QChar *head; + const QChar *json; + const QChar *end; + + int nestingLevel; + QJsonParseError::ParseError lastError; +}; + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 82b20337cb..3cc77d2e3d 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -33,6 +33,7 @@ #include "qv4lookup_p.h" #include "qv4functionobject_p.h" #include "qv4scopedvalue_p.h" +#include "qv4string_p.h" QT_BEGIN_NAMESPACE @@ -72,7 +73,7 @@ ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttribu return Primitive::emptyValue().asReturnedValue(); } -ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs) +ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs) { Heap::Object *obj = thisObject->d(); ExecutionEngine *engine = thisObject->engine(); @@ -123,7 +124,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const Value &object, cons ScopedObject o(scope, object); if (!o) { if (idx < UINT_MAX) { - if (String *str = object.asString()) { + if (const String *str = object.as<String>()) { if (idx >= (uint)str->toQString().length()) { return Encode::undefined(); } @@ -168,7 +169,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con Object *o = object.objectValue(); if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { - Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (idx < s->len) if (!s->data(idx).isEmpty()) return s->data(idx).asReturnedValue(); @@ -200,7 +201,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value & uint idx = index.asArrayIndex(); if (idx < UINT_MAX) { if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { - Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (idx < s->len) { s->data(idx) = value; return; @@ -224,7 +225,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value Object *o = object.objectValue(); if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { - Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); if (idx < s->len) { s->data(idx) = v; return; @@ -235,7 +236,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object) { - if (Object *o = object.asObject()) + if (const Object *o = object.as<Object>()) return o->getLookup(l); Object *proto; @@ -244,11 +245,11 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va case Value::Null_Type: return engine->throwTypeError(); case Value::Boolean_Type: - proto = engine->booleanPrototype.asObject(); + proto = engine->booleanPrototype(); break; case Value::Managed_Type: { Q_ASSERT(object.isString()); - proto = engine->stringPrototype.asObject(); + proto = engine->stringPrototype(); Scope scope(engine); ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]); if (name->equals(engine->id_length)) { @@ -260,7 +261,7 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va } case Value::Integer_Type: default: // Number - proto = engine->numberPrototype.asObject(); + proto = engine->numberPrototype(); } PropertyAttributes attrs; @@ -291,7 +292,7 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Lookup l1 = *l; if (l1.getter == Lookup::getter0 || l1.getter == Lookup::getter1) { - if (Object *o = object.asObject()) { + if (const Object *o = object.as<Object>()) { ReturnedValue v = o->getLookup(l); Lookup l2 = *l; @@ -560,7 +561,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object) { - if (String *s = object.asString()) + if (const String *s = object.as<String>()) return Encode(s->d()->length()); l->getter = getterGeneric; @@ -569,7 +570,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, con ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object) { - if (ArrayObject *a = object.asArrayObject()) + if (const ArrayObject *a = object.as<ArrayObject>()) return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue(); l->getter = getterGeneric; @@ -579,7 +580,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, cons ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine) { - Object *o = engine->globalObject(); + Object *o = engine->globalObject; PropertyAttributes attrs; ReturnedValue v = l->lookup(o, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { @@ -608,7 +609,7 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine) { - Object *o = engine->globalObject(); + Object *o = engine->globalObject; if (l->classList[0] == o->internalClass()) return o->memberData()->data[l->index].asReturnedValue(); @@ -618,7 +619,7 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine) { - Object *o = engine->globalObject(); + Object *o = engine->globalObject; if (l->classList[0] == o->internalClass() && l->classList[1] == o->prototype()->internalClass) return o->prototype()->memberData->data[l->index].asReturnedValue(); @@ -629,7 +630,7 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine) { - Heap::Object *o = engine->globalObject()->d(); + Heap::Object *o = engine->globalObject->d(); if (l->classList[0] == o->internalClass) { o = o->prototype; if (l->classList[1] == o->internalClass) { @@ -645,7 +646,7 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine) { - Object *o = engine->globalObject(); + Object *o = engine->globalObject; if (l->classList[0] == o->internalClass()) { Scope scope(o->engine()); ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter()); @@ -662,7 +663,7 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine) { - Object *o = engine->globalObject(); + Object *o = engine->globalObject; if (l->classList[0] == o->internalClass() && l->classList[1] == o->prototype()->internalClass) { Scope scope(o->engine()); @@ -680,7 +681,7 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine) ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine) { - Heap::Object *o = engine->globalObject()->d(); + Heap::Object *o = engine->globalObject->d(); if (l->classList[0] == o->internalClass) { o = o->prototype; if (l->classList[1] == o->internalClass) { @@ -701,7 +702,7 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine) return globalGetterGeneric(l, engine); } -void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { Scope scope(engine); ScopedObject o(scope, object); @@ -716,11 +717,11 @@ void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &obje o->setLookup(l, value); } -void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { Lookup l1 = *l; - if (Object *o = object.asObject()) { + if (Object *o = object.as<Object>()) { o->setLookup(l, value); if (l->setter == Lookup::setter0) { @@ -735,7 +736,7 @@ void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &o setterFallback(l, engine, object, value); } -void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { QV4::Scope scope(engine); QV4::ScopedObject o(scope, object.toObject(scope.engine)); @@ -745,9 +746,9 @@ void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const Value &obj } } -void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { - Object *o = static_cast<Object *>(object.asManaged()); + Object *o = object.as<Object>(); if (o && o->internalClass() == l->classList[0]) { o->memberData()->data[l->index] = value; return; @@ -756,9 +757,9 @@ void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const Value &object, co setterTwoClasses(l, engine, object, value); } -void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { - Object *o = static_cast<Object *>(object.asManaged()); + Object *o = object.as<Object>(); if (o && o->internalClass() == l->classList[0]) { if (!o->prototype()) { if (!o->memberData() || l->index >= o->memberData()->size) @@ -773,9 +774,9 @@ void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &obje setterFallback(l, engine, object, value); } -void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { - Object *o = static_cast<Object *>(object.asManaged()); + Object *o = object.as<Object>(); if (o && o->internalClass() == l->classList[0]) { Heap::Object *p = o->prototype(); if (p && p->internalClass == l->classList[1]) { @@ -791,9 +792,9 @@ void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &obje setterFallback(l, engine, object, value); } -void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { - Object *o = static_cast<Object *>(object.asManaged()); + Object *o = object.as<Object>(); if (o && o->internalClass() == l->classList[0]) { Heap::Object *p = o->prototype(); if (p && p->internalClass == l->classList[1]) { @@ -812,9 +813,9 @@ void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &obje setterFallback(l, engine, object, value); } -void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value) +void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value) { - Object *o = static_cast<Object *>(object.asManaged()); + Object *o = object.as<Object>(); if (o) { if (o->internalClass() == l->classList[0]) { o->memberData()->data[l->index] = value; diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 88397dc36c..232e909c48 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -51,7 +51,7 @@ struct Lookup { void (*indexedSetter)(Lookup *l, const Value &object, const Value &index, const Value &v); ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object); ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine); - void (*setter)(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &v); + void (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v); }; union { ExecutionEngine *engine; @@ -107,17 +107,17 @@ struct Lookup { static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine); static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine); - static void setterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setterFallback(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setterInsert0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setterInsert1(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setterInsert2(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); - static void setter0setter0(Lookup *l, ExecutionEngine *engine, const Value &object, const Value &value); + static void setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setterInsert0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setterInsert1(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setterInsert2(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); + static void setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value); ReturnedValue lookup(const Value &thisObject, Object *obj, PropertyAttributes *attrs); - ReturnedValue lookup(Object *obj, PropertyAttributes *attrs); + ReturnedValue lookup(const Object *obj, PropertyAttributes *attrs); }; diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index c4b9fc597e..546190086e 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -32,13 +32,13 @@ ****************************************************************************/ #include "qv4managed_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4errorobject_p.h" using namespace QV4; -const ManagedVTable Managed::static_vtbl = +const VTable Managed::static_vtbl = { 0, Managed::IsExecutionContext, diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 0fe5c7ee49..7cce80d087 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -35,7 +35,7 @@ #include "qv4global_p.h" #include "qv4value_p.h" -#include "qv4internalclass_p.h" +#include <private/qv4heap_p.h> QT_BEGIN_NAMESPACE @@ -65,8 +65,8 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} Q_MANAGED_CHECK \ typedef QV4::Heap::DataClass Data; \ typedef superClass SuperClass; \ - static const QV4::ManagedVTable static_vtbl; \ - static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \ + static const QV4::VTable static_vtbl; \ + static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \ V4_MANAGED_SIZE_TEST \ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); } @@ -86,23 +86,6 @@ struct GCDeletable bool lastCall; }; -struct ManagedVTable -{ - const ManagedVTable * const parent; - uint isExecutionContext : 1; - uint isString : 1; - uint isObject : 1; - uint isFunctionObject : 1; - uint isErrorObject : 1; - uint isArrayData : 1; - uint unused : 18; - uint type : 8; - const char *className; - void (*destroy)(Heap::Base *); - void (*markObjects)(Heap::Base *, ExecutionEngine *e); - bool (*isEqualTo)(Managed *m, Managed *other); -}; - #define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \ { \ parentVTable, \ @@ -121,7 +104,7 @@ struct ManagedVTable } #define DEFINE_MANAGED_VTABLE(classname) \ -const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) +const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) struct Q_QML_PRIVATE_EXPORT Managed : Value { @@ -141,8 +124,6 @@ private: public: - inline void mark(QV4::ExecutionEngine *engine); - enum Type { Type_Invalid, Type_String, @@ -167,46 +148,6 @@ public: }; Q_MANAGED_TYPE(Invalid) - template <typename T> - T *as() { - Q_ASSERT(d()->vtable); -#if !defined(QT_NO_QOBJECT_CHECK) - static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this)); -#endif - const ManagedVTable *vt = d()->vtable; - while (vt) { - if (vt == T::staticVTable()) - return static_cast<T *>(this); - vt = vt->parent; - } - return 0; - } - template <typename T> - const T *as() const { - Q_ASSERT(d()->vtable); -#if !defined(QT_NO_QOBJECT_CHECK) - static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this))); -#endif - const ManagedVTable *vt = d()->vtable; - while (vt) { - if (vt == T::staticVTable()) - return static_cast<T *>(this); - vt = vt->parent; - } - return 0; - } - - String *asString() { return d()->vtable->isString ? reinterpret_cast<String *>(this) : 0; } - Object *asObject() { return d()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; } - ArrayObject *asArrayObject() { return d()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; } - FunctionObject *asFunctionObject() { return d()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; } - BooleanObject *asBooleanObject() { return d()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; } - NumberObject *asNumberObject() { return d()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; } - StringObject *asStringObject() { return d()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; } - DateObject *asDateObject() { return d()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; } - ErrorObject *asErrorObject() { return d()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; } - ArgumentsObject *asArgumentsObject() { return d()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; } - bool isListType() const { return d()->vtable->type == Type_QmlSequence; } bool isArrayObject() const { return d()->vtable->type == Type_ArrayObject; } @@ -231,37 +172,15 @@ private: template<> -inline Managed *value_cast(const Value &v) { - return v.asManaged(); -} - -template<typename T> -inline T *managed_cast(Managed *m) -{ - return m ? m->as<T>() : 0; +inline const Managed *Value::as() const { + if (isManaged()) + return managed(); + return 0; } template<> -inline String *managed_cast(Managed *m) -{ - return m ? m->asString() : 0; -} -template<> -inline Object *managed_cast(Managed *m) -{ - return m ? m->asObject() : 0; -} -template<> -inline FunctionObject *managed_cast(Managed *m) -{ - return m ? m->asFunctionObject() : 0; -} - -inline Value Value::fromManaged(Managed *m) -{ - if (!m) - return QV4::Primitive::undefinedValue(); - return *m; +inline const Object *Value::as() const { + return isManaged() && m && m->vtable->isObject ? objectValue() : 0; } } diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 473e05bf88..c498160c36 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -48,7 +48,7 @@ DEFINE_OBJECT_VTABLE(MathObject); static const double qt_PI = 2.0 * ::asin(1.0); Heap::MathObject::MathObject(ExecutionEngine *e) - : Heap::Object(e->emptyClass, e->objectPrototype.asObject()) + : Heap::Object(e->emptyClass, e->objectPrototype()) { Scope scope(e); ScopedObject m(scope, this); diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index 03dfee3dcf..5ec5cb1f58 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -32,7 +32,8 @@ ****************************************************************************/ #include "qv4memberdata_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> +#include "qv4value_p.h" using namespace QV4; diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 89ff110b20..3b71971433 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -33,6 +33,7 @@ #include "qv4numberobject_p.h" #include "qv4runtime_p.h" +#include "qv4string_p.h" #include <QtCore/qnumeric.h> #include <QtCore/qmath.h> @@ -50,14 +51,14 @@ Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope) { } -ReturnedValue NumberCtor::construct(Managed *m, CallData *callData) +ReturnedValue NumberCtor::construct(const Managed *m, CallData *callData) { Scope scope(m->cast<NumberCtor>()->engine()); double dbl = callData->argc ? callData->args[0].toNumber() : 0.; return Encode(scope.engine->newNumberObject(dbl)); } -ReturnedValue NumberCtor::call(Managed *, CallData *callData) +ReturnedValue NumberCtor::call(const Managed *, CallData *callData) { double dbl = callData->argc ? callData->args[0].toNumber() : 0.; return Encode(dbl); @@ -97,7 +98,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx) { if (ctx->thisObject().isNumber()) return ctx->thisObject().asReturnedValue(); - NumberObject *n = ctx->thisObject().asNumberObject(); + NumberObject *n = ctx->thisObject().as<NumberObject>(); if (!n) return ctx->engine()->throwTypeError(); return Encode(n->value()); @@ -107,7 +108,7 @@ inline double thisNumber(ExecutionContext *ctx) { if (ctx->thisObject().isNumber()) return ctx->thisObject().asDouble(); - NumberObject *n = ctx->thisObject().asNumberObject(); + NumberObject *n = ctx->thisObject().as<NumberObject>(); if (!n) return ctx->engine()->throwTypeError(); return n->value(); diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 205995701b..04798d31fc 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -53,8 +53,8 @@ struct NumberCtor: FunctionObject { V4_OBJECT2(NumberCtor, FunctionObject) - static ReturnedValue construct(Managed *that, CallData *callData); - static ReturnedValue call(Managed *, CallData *callData); + static ReturnedValue construct(const Managed *that, CallData *callData); + static ReturnedValue call(const Managed *, CallData *callData); }; struct NumberPrototype: NumberObject diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 211fd1812e..148c7829bd 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -37,12 +37,13 @@ #include "qv4objectproto_p.h" #include "qv4stringobject_p.h" #include "qv4argumentsobject_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4lookup_p.h" #include "qv4scopedvalue_p.h" #include "qv4memberdata_p.h" #include "qv4objectiterator_p.h" #include "qv4identifier_p.h" +#include "qv4string_p.h" #include <stdint.h> @@ -356,7 +357,7 @@ bool Object::hasOwnProperty(uint index) const return true; if (isStringObject()) { - String *s = static_cast<const StringObject *>(this)->d()->value.asString(); + String *s = static_cast<const StringObject *>(this)->d()->value.as<String>(); if (index < (uint)s->d()->length()) return true; } @@ -365,24 +366,24 @@ bool Object::hasOwnProperty(uint index) const return false; } -ReturnedValue Object::construct(Managed *m, CallData *) +ReturnedValue Object::construct(const Managed *m, CallData *) { - return static_cast<Object *>(m)->engine()->throwTypeError(); + return static_cast<const Object *>(m)->engine()->throwTypeError(); } -ReturnedValue Object::call(Managed *m, CallData *) +ReturnedValue Object::call(const Managed *m, CallData *) { - return static_cast<Object *>(m)->engine()->throwTypeError(); + return static_cast<const Object *>(m)->engine()->throwTypeError(); } -ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty) { - return static_cast<Object *>(m)->internalGet(name, hasProperty); + return static_cast<const Object *>(m)->internalGet(name, hasProperty); } -ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty) { - return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty); + return static_cast<const Object *>(m)->internalGetIndexed(index, hasProperty); } void Object::put(Managed *m, String *name, const Value &value) @@ -416,7 +417,7 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index) return o->arrayData()->attributes(index); if (o->isStringObject()) { - String *s = static_cast<const StringObject *>(o)->d()->value.asString(); + String *s = static_cast<const StringObject *>(o)->d()->value.as<String>(); if (index < (uint)s->d()->length()) return (Attr_NotWritable|Attr_NotConfigurable); } @@ -433,9 +434,9 @@ bool Object::deleteIndexedProperty(Managed *m, uint index) return static_cast<Object *>(m)->internalDeleteIndexedProperty(index); } -ReturnedValue Object::getLookup(Managed *m, Lookup *l) +ReturnedValue Object::getLookup(const Managed *m, Lookup *l) { - Object *o = static_cast<Object *>(m); + const Object *o = static_cast<const Object *>(m); PropertyAttributes attrs; ReturnedValue v = l->lookup(o, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { @@ -531,7 +532,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name while (it->arrayNode != o->sparseEnd()) { int k = it->arrayNode->key(); uint pidx = it->arrayNode->value; - Heap::SparseArrayData *sa = static_cast<Heap::SparseArrayData *>(o->d()->arrayData); + Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>(); Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx); it->arrayNode = it->arrayNode->nextNode(); PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data; @@ -548,7 +549,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name } // dense arrays while (it->arrayIndex < o->d()->arrayData->len) { - Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData); + Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Value &val = sa->data(it->arrayIndex); PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex); ++it->arrayIndex; @@ -585,7 +586,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name } // Section 8.12.3 -ReturnedValue Object::internalGet(String *name, bool *hasProperty) +ReturnedValue Object::internalGet(String *name, bool *hasProperty) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -611,7 +612,7 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty) return Encode::undefined(); } -ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) +ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const { Property *pd = 0; PropertyAttributes attrs; @@ -710,7 +711,7 @@ void Object::internalPut(String *name, const Value &value) // Clause 5 if (pd && attrs.isAccessor()) { - assert(pd->setter() != 0); + Q_ASSERT(pd->setter() != 0); Scope scope(engine()); ScopedFunctionObject setter(scope, pd->setter()); @@ -784,7 +785,7 @@ void Object::internalPutIndexed(uint index, const Value &value) // Clause 5 if (pd && attrs.isAccessor()) { - assert(pd->setter() != 0); + Q_ASSERT(pd->setter() != 0); Scope scope(engine()); ScopedFunctionObject setter(scope, pd->setter()); @@ -1137,7 +1138,7 @@ void Object::initSparseArray() DEFINE_OBJECT_VTABLE(ArrayObject); Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) - : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject()) + : Heap::Object(engine->arrayClass, engine->arrayPrototype()) { init(); Scope scope(engine); @@ -1155,14 +1156,14 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) a->setArrayLengthUnchecked(len); } -ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l) +ReturnedValue ArrayObject::getLookup(const Managed *m, Lookup *l) { - Scope scope(static_cast<Object *>(m)->engine()); + Scope scope(static_cast<const Object *>(m)->engine()); ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]); if (name->equals(scope.engine->id_length)) { // special case, as the property is on the object itself l->getter = Lookup::arrayLengthGetter; - ArrayObject *a = static_cast<ArrayObject *>(m); + const ArrayObject *a = static_cast<const ArrayObject *>(m); return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue(); } return Object::getLookup(m, l); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 71a997e133..e5055e20c0 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -36,6 +36,9 @@ #include "qv4managed_p.h" #include "qv4memberdata_p.h" #include "qv4arraydata_p.h" +#include "qv4engine_p.h" +#include "qv4scopedvalue_p.h" +#include "qv4value_p.h" QT_BEGIN_NAMESPACE @@ -44,20 +47,16 @@ namespace QV4 { namespace Heap { struct Object : Base { - Object(ExecutionEngine *engine) - : internalClass(engine->emptyClass), - prototype(static_cast<Object *>(engine->objectPrototype.m)) - { - } + inline Object(ExecutionEngine *engine); Object(InternalClass *internal, QV4::Object *prototype); const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData->data + index); } Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData->data + index); } InternalClass *internalClass; - Heap::Object *prototype; - MemberData *memberData; - ArrayData *arrayData; + Pointer<Object> prototype; + Pointer<MemberData> memberData; + Pointer<ArrayData> arrayData; }; } @@ -67,7 +66,7 @@ struct Object : Base { Q_MANAGED_CHECK \ typedef superClass SuperClass; \ static const QV4::ObjectVTable static_vtbl; \ - static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \ + static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \ V4_MANAGED_SIZE_TEST \ Data *d() const { return static_cast<Data *>(m); } @@ -77,24 +76,24 @@ struct Object : Base { typedef QV4::Heap::DataClass Data; \ typedef superClass SuperClass; \ static const QV4::ObjectVTable static_vtbl; \ - static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \ + static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \ V4_MANAGED_SIZE_TEST \ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); } struct ObjectVTable { - ManagedVTable managedVTable; - ReturnedValue (*call)(Managed *, CallData *data); - ReturnedValue (*construct)(Managed *, CallData *data); - ReturnedValue (*get)(Managed *, String *name, bool *hasProperty); - ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty); + VTable vTable; + ReturnedValue (*call)(const Managed *, CallData *data); + ReturnedValue (*construct)(const Managed *, CallData *data); + ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty); + ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty); void (*put)(Managed *, String *name, const Value &value); void (*putIndexed)(Managed *, uint index, const Value &value); PropertyAttributes (*query)(const Managed *, String *name); PropertyAttributes (*queryIndexed)(const Managed *, uint index); bool (*deleteProperty)(Managed *m, String *name); bool (*deleteIndexedProperty)(Managed *m, uint index); - ReturnedValue (*getLookup)(Managed *m, Lookup *l); + ReturnedValue (*getLookup)(const Managed *m, Lookup *l); void (*setLookup)(Managed *m, Lookup *l, const Value &v); uint (*getLength)(const Managed *m); void (*advanceIterator)(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes); @@ -103,7 +102,7 @@ struct ObjectVTable #define DEFINE_OBJECT_VTABLE(classname) \ const QV4::ObjectVTable classname::static_vtbl = \ { \ - DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \ + DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.vTable), \ call, \ construct, \ get, \ @@ -272,9 +271,9 @@ public: } void ensureMemberIndex(uint idx); - inline ReturnedValue get(String *name, bool *hasProperty = 0) + inline ReturnedValue get(String *name, bool *hasProperty = 0) const { return vtable()->get(this, name, hasProperty); } - inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) + inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) const { return vtable()->getIndexed(this, idx, hasProperty); } inline void put(String *name, const Value &v) { vtable()->put(this, name, v); } @@ -288,7 +287,7 @@ public: { return vtable()->deleteProperty(this, name); } bool deleteIndexedProperty(uint index) { return vtable()->deleteIndexedProperty(this, index); } - ReturnedValue getLookup(Lookup *l) + ReturnedValue getLookup(Lookup *l) const { return vtable()->getLookup(this, l); } void setLookup(Lookup *l, const Value &v) { vtable()->setLookup(this, l, v); } @@ -296,30 +295,30 @@ public: { vtable()->advanceIterator(this, it, name, index, p, attributes); } uint getLength() const { return vtable()->getLength(this); } - inline ReturnedValue construct(CallData *d) + inline ReturnedValue construct(CallData *d) const { return vtable()->construct(this, d); } - inline ReturnedValue call(CallData *d) + inline ReturnedValue call(CallData *d) const { return vtable()->call(this, d); } protected: static void markObjects(Heap::Base *that, ExecutionEngine *e); - static ReturnedValue construct(Managed *m, CallData *); - static ReturnedValue call(Managed *m, CallData *); - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue construct(const Managed *m, CallData *); + static ReturnedValue call(const Managed *m, CallData *); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); static void putIndexed(Managed *m, uint index, const Value &value); static PropertyAttributes query(const Managed *m, String *name); static PropertyAttributes queryIndexed(const Managed *m, uint index); static bool deleteProperty(Managed *m, String *name); static bool deleteIndexedProperty(Managed *m, uint index); - static ReturnedValue getLookup(Managed *m, Lookup *l); + static ReturnedValue getLookup(const Managed *m, Lookup *l); static void setLookup(Managed *m, Lookup *l, const Value &v); static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes); static uint getLength(const Managed *m); private: - ReturnedValue internalGet(String *name, bool *hasProperty); - ReturnedValue internalGetIndexed(uint index, bool *hasProperty); + ReturnedValue internalGet(String *name, bool *hasProperty) const; + ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const; void internalPut(String *name, const Value &value); void internalPutIndexed(uint index, const Value &value); bool internalDeleteProperty(String *name); @@ -331,6 +330,12 @@ private: namespace Heap { +inline Object::Object(ExecutionEngine *engine) + : internalClass(engine->emptyClass), + prototype(static_cast<Object *>(engine->objectPrototype()->m)) +{ +} + struct BooleanObject : Object { BooleanObject(InternalClass *ic, QV4::Object *prototype) : Object(ic, prototype), @@ -339,7 +344,7 @@ struct BooleanObject : Object { } BooleanObject(ExecutionEngine *engine, bool b) - : Object(engine->emptyClass, engine->booleanPrototype.asObject()), + : Object(engine->emptyClass, engine->booleanPrototype()), b(b) { } @@ -354,7 +359,7 @@ struct NumberObject : Object { } NumberObject(ExecutionEngine *engine, double val) - : Object(engine->emptyClass, engine->numberPrototype.asObject()), + : Object(engine->emptyClass, engine->numberPrototype()), value(val) { } @@ -367,7 +372,7 @@ struct ArrayObject : Object { }; ArrayObject(ExecutionEngine *engine) - : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject()) + : Heap::Object(engine->arrayClass, engine->arrayPrototype()) { init(); } ArrayObject(ExecutionEngine *engine, const QStringList &list); ArrayObject(InternalClass *ic, QV4::Object *prototype) @@ -400,7 +405,7 @@ struct ArrayObject: Object { void init(ExecutionEngine *engine); - static ReturnedValue getLookup(Managed *m, Lookup *l); + static ReturnedValue getLookup(const Managed *m, Lookup *l); using Object::getLength; static uint getLength(const Managed *m); @@ -454,14 +459,10 @@ inline void Object::arraySet(uint index, const Value &value) setArrayLengthUnchecked(index + 1); } -template<> -inline Object *value_cast(const Value &v) { - return v.asObject(); -} template<> -inline ArrayObject *value_cast(const Value &v) { - return v.asArrayObject(); +inline const ArrayObject *Value::as() const { + return isManaged() && m && m->vtable->type == Managed::Type_ArrayObject ? static_cast<const ArrayObject *>(this) : 0; } #ifndef V4_BOOTSTRAP diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index f36ee554a7..3901101855 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -35,6 +35,7 @@ #include "qv4stringobject_p.h" #include "qv4identifier_p.h" #include "qv4argumentsobject_p.h" +#include "qv4string_p.h" using namespace QV4; @@ -83,7 +84,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper *name = 0; *index = UINT_MAX; - if (!object->asObject()) { + if (!object->as<Object>()) { *attrs = PropertyAttributes(); return; } @@ -92,19 +93,19 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper ScopedString n(scope); while (1) { - if (!current->asObject()) + if (!current->as<Object>()) break; while (1) { - current->asObject()->advanceIterator(this, name, index, pd, attrs); + current->as<Object>()->advanceIterator(this, name, index, pd, attrs); if (attrs->isEmpty()) break; // check the property is not already defined earlier in the proto chain if (current->heapObject() != object->heapObject()) { - o = object->asObject(); + o = object->as<Object>(); n = *name; bool shadowed = false; - while (o->asObject()->d() != current->heapObject()) { + while (o->d() != current->heapObject()) { if ((!!n && o->hasOwnProperty(n)) || (*index != UINT_MAX && o->hasOwnProperty(*index))) { shadowed = true; @@ -131,7 +132,7 @@ void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, Proper ReturnedValue ObjectIterator::nextPropertyName(Value *value) { - if (!object->asObject()) + if (!object->as<Object>()) return Encode::null(); PropertyAttributes attrs; @@ -147,13 +148,13 @@ ReturnedValue ObjectIterator::nextPropertyName(Value *value) if (!!name) return name->asReturnedValue(); - assert(index < UINT_MAX); + Q_ASSERT(index < UINT_MAX); return Encode(index); } ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value) { - if (!object->asObject()) + if (!object->as<Object>()) return Encode::null(); PropertyAttributes attrs; @@ -169,13 +170,13 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value) if (!!name) return name->asReturnedValue(); - assert(index < UINT_MAX); + Q_ASSERT(index < UINT_MAX); return Encode(engine->newString(QString::number(index))); } ReturnedValue ObjectIterator::nextPropertyNameAsString() { - if (!object->asObject()) + if (!object->as<Object>()) return Encode::null(); PropertyAttributes attrs; diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 9356ea434e..bac5da709e 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -34,10 +34,11 @@ #include "qv4objectproto_p.h" #include "qv4argumentsobject_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4scopedvalue_p.h" #include "qv4runtime_p.h" #include "qv4objectiterator_p.h" +#include "qv4string_p.h" #include <QtCore/QDateTime> #include <QtCore/QStringList> @@ -52,9 +53,9 @@ Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope) { } -ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData) +ReturnedValue ObjectCtor::construct(const Managed *that, CallData *callData) { - ObjectCtor *ctor = static_cast<ObjectCtor *>(that); + const ObjectCtor *ctor = static_cast<const ObjectCtor *>(that); ExecutionEngine *v4 = ctor->engine(); Scope scope(v4); if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) { @@ -67,9 +68,9 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData) return RuntimeHelpers::toObject(scope.engine, callData->args[0]); } -ReturnedValue ObjectCtor::call(Managed *m, CallData *callData) +ReturnedValue ObjectCtor::call(const Managed *m, CallData *callData) { - ObjectCtor *ctor = static_cast<ObjectCtor *>(m); + const ObjectCtor *ctor = static_cast<const ObjectCtor *>(m); ExecutionEngine *v4 = ctor->engine(); if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) return v4->newObject()->asReturnedValue(); @@ -163,7 +164,7 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx) return ctx->engine()->throwTypeError(); ScopedObject newObject(scope, ctx->d()->engine->newObject()); - newObject->setPrototype(O->asObject()); + newObject->setPrototype(O->as<Object>()); if (ctx->argc() > 1 && !ctx->args()[1].isUndefined()) { ctx->d()->callData->args[0] = newObject.asReturnedValue(); @@ -484,7 +485,7 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx) if (!o) { if (!ctx->thisObject().isUndefined()) return Encode::undefined(); - o = ctx->d()->engine->globalObject(); + o = ctx->d()->engine->globalObject; } ScopedProperty pd(scope); @@ -512,7 +513,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx) if (!o) { if (!ctx->thisObject().isUndefined()) return Encode::undefined(); - o = ctx->d()->engine->globalObject(); + o = ctx->d()->engine->globalObject; } ScopedProperty pd(scope); @@ -525,7 +526,7 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx) ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx) { Scope scope(ctx); - ScopedObject o(scope, ctx->thisObject().asObject()); + ScopedObject o(scope, ctx->thisObject().as<Object>()); if (!o) return ctx->engine()->throwTypeError(); @@ -580,7 +581,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value if (o->hasProperty(engine->id_get)) { ScopedValue get(scope, o->get(engine->id_get)); - FunctionObject *f = get->asFunctionObject(); + FunctionObject *f = get->as<FunctionObject>(); if (f || get->isUndefined()) { desc->value = get; } else { @@ -592,7 +593,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const Value if (o->hasProperty(engine->id_set)) { ScopedValue set(scope, o->get(engine->id_set)); - FunctionObject *f = set->asFunctionObject(); + FunctionObject *f = set->as<FunctionObject>(); if (f || set->isUndefined()) { desc->set = set; } else { diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index 4e96681017..d571e50cd4 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -53,8 +53,8 @@ struct ObjectCtor: FunctionObject { V4_OBJECT2(ObjectCtor, FunctionObject) - static ReturnedValue construct(Managed *that, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *that, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct ObjectPrototype: Object diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 88dc1946b8..f7e88dddd6 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -32,7 +32,7 @@ ****************************************************************************/ #include "qv4persistent_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4object_p.h" #include "PageAllocation.h" @@ -190,7 +190,7 @@ void PersistentValueStorage::mark(ExecutionEngine *e) Page *p = static_cast<Page *>(firstPage); while (p) { for (int i = 0; i < kEntriesPerPage; ++i) { - if (Managed *m = p->values[i].asManaged()) + if (Managed *m = p->values[i].as<Managed>()) m->mark(e); } drainMarkStack(e, markBase); diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index 7cac2ed95f..fe50b0ebfc 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -33,7 +33,8 @@ #ifndef QV4PERSISTENT_H #define QV4PERSISTENT_H -#include "qv4value_inl_p.h" +#include "qv4value_p.h" +#include "qv4managed_p.h" QT_BEGIN_NAMESPACE @@ -96,7 +97,7 @@ public: Managed *asManaged() const { if (!val) return 0; - return val->asManaged(); + return val->as<Managed>(); } ExecutionEngine *engine() const { @@ -138,7 +139,7 @@ public: Managed *asManaged() const { if (!val) return 0; - return val->asManaged(); + return val->as<Managed>(); } ExecutionEngine *engine() const { diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index a7019d0558..d2628c7bd0 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -32,7 +32,8 @@ ****************************************************************************/ #include "qv4profiling_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> +#include <private/qv4string_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h index 1b55abd1f7..34d9cdadeb 100644 --- a/src/qml/jsruntime/qv4property_p.h +++ b/src/qml/jsruntime/qv4property_p.h @@ -35,7 +35,6 @@ #include "qv4global_p.h" #include "qv4value_p.h" -#include "qv4internalclass_p.h" QT_BEGIN_NAMESPACE @@ -73,8 +72,8 @@ struct Property { inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; } inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; } - inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); } - inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); } + inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); } + inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : 0); } void copy(const Property *other, PropertyAttributes attrs) { value = other->value; @@ -85,8 +84,8 @@ struct Property { explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); } explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); } Property(FunctionObject *getter, FunctionObject *setter) { - value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter)); - set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter)); + value = reinterpret_cast<Managed *>(getter); + set = reinterpret_cast<Managed *>(setter); } Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) { value.m = reinterpret_cast<Heap::Base *>(getter); diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 1e4718c208..e985c62228 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -55,6 +55,7 @@ #include <private/qv4objectproto_p.h> #include <private/qv4jsonobject_p.h> #include <private/qv4regexpobject_p.h> +#include <private/qv4dateobject_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qv4mm_p.h> #include <private/qqmlscriptstring_p.h> @@ -97,7 +98,7 @@ static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function) static QPair<QObject *, int> extractQtSignal(const Value &value) { if (value.isObject()) { - QV4::ExecutionEngine *v4 = value.asObject()->engine(); + QV4::ExecutionEngine *v4 = value.as<Object>()->engine(); QV4::Scope scope(v4); QV4::ScopedFunctionObject function(scope, value); if (function) @@ -240,8 +241,8 @@ Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object) void QObjectWrapper::initializeBindings(ExecutionEngine *engine) { - engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect); - engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect); + engine->functionPrototype()->defineDefaultProperty(QStringLiteral("connect"), method_connect); + engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect); } QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const @@ -260,7 +261,7 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont } ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode, - bool *hasProperty, bool includeImports) + bool *hasProperty, bool includeImports) const { if (QQmlData::wasDeleted(d()->object)) { if (hasProperty) @@ -346,8 +347,8 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect"))); QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect"))); - handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect))); - handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(disconnect))); + handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype()->get(connect))); + handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype()->get(disconnect))); return handler.asReturnedValue(); } else { @@ -476,14 +477,14 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro bindingFunction->initBindingLocation(); newBinding = new QQmlBinding(value, object, callingQmlContext); - newBinding->setTarget(object, *property, callingQmlContext); + newBinding->setTarget(object, *property); } } - QQmlAbstractBinding *oldBinding = - QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding); - if (oldBinding) - oldBinding->destroy(); + if (newBinding) + QQmlPropertyPrivate::setBinding(newBinding); + else + QQmlPropertyPrivate::removeBinding(object, property->encodedIndex(), QQmlPropertyPrivate::DestroyOldBinding); if (!newBinding && property->isVarProperty()) { // allow assignment of "special" values (null, undefined, function) to var properties @@ -519,7 +520,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro error += QLatin1String(QMetaType::typeName(property->propType)); ctx->engine()->throwError(error); return; - } else if (value.asFunctionObject()) { + } else if (value.as<FunctionObject>()) { // this is handled by the binding creation above } else if (property->propType == QMetaType::Int && value.isNumber()) { PROPERTY_STORE(int, value.asDouble()); @@ -673,7 +674,7 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b) { Q_ASSERT(a->as<QV4::QObjectWrapper>()); QV4::QObjectWrapper *qobjectWrapper = static_cast<QV4::QObjectWrapper *>(a); - QV4::Object *o = b->asObject(); + QV4::Object *o = b->as<Object>(); if (o) { if (QV4::QmlTypeWrapper *qmlTypeWrapper = o->as<QV4::QmlTypeWrapper>()) return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object(); @@ -689,9 +690,9 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue(); } -QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty) +QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty) { - QObjectWrapper *that = static_cast<QObjectWrapper*>(m); + const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m); QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(that->engine()); return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true); } @@ -816,7 +817,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase QV4::ScopedFunctionObject f(scope, This->function.value()); QV4::ScopedCallData callData(scope, argCount); - callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject()->asReturnedValue() : This->thisObject.value(); + callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value(); for (int ii = 0; ii < argCount; ++ii) { int type = argsTypes[ii + 1]; if (type == qMetaTypeId<QVariant>()) { @@ -1234,7 +1235,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType) default: return 10; } - } else if (actual.asDateObject()) { + } else if (actual.as<DateObject>()) { switch (conversionType) { case QMetaType::QDateTime: return 0; @@ -1252,7 +1253,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType) default: return 10; } - } else if (actual.asArrayObject()) { + } else if (actual.as<ArrayObject>()) { switch (conversionType) { case QMetaType::QJsonArray: return 3; @@ -1281,7 +1282,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType) return 10; } } - } else if (QV4::Object *obj = actual.asObject()) { + } else if (const Object *obj = actual.as<Object>()) { if (obj->as<QV4::VariantObject>()) { if (conversionType == qMetaTypeId<QVariant>()) return 0; @@ -1611,9 +1612,9 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q type = callType; } else if (callType == QMetaType::QObjectStar) { qobjectPtr = 0; - if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) + if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) qobjectPtr = qobjectWrapper->object(); - else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>()) + else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>()) queryEngine = qmlTypeWrapper->isSingleton(); type = callType; } else if (callType == qMetaTypeId<QVariant>()) { @@ -1635,7 +1636,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q } } else { QObject *o = 0; - if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) + if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) o = qobjectWrapper->object(); qlistPtr->append(o); } @@ -1759,14 +1760,14 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in return method.asReturnedValue(); } -ReturnedValue QObjectMethod::create(ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal) +ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal) { Scope valueScope(scope); Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope)); method->d()->propertyCache = valueType->d()->propertyCache; method->d()->index = index; method->d()->qmlGlobal = qmlGlobal; - method->d()->valueTypeWrapper = valueType; + method->d()->valueTypeWrapper = *valueType; return method.asReturnedValue(); } @@ -1782,7 +1783,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject() return object->metaObject(); } -QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) +QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const { QString result; if (const QMetaObject *metaObject = d()->metaObject()) { @@ -1808,7 +1809,7 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) return ctx->d()->engine->newString(result)->asReturnedValue(); } -QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) +QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const { if (!d()->object) return Encode::undefined(); @@ -1827,13 +1828,13 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con return Encode::undefined(); } -ReturnedValue QObjectMethod::call(Managed *m, CallData *callData) +ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData) { - QObjectMethod *This = static_cast<QObjectMethod*>(m); + const QObjectMethod *This = static_cast<const QObjectMethod*>(m); return This->callInternal(callData); } -ReturnedValue QObjectMethod::callInternal(CallData *callData) +ReturnedValue QObjectMethod::callInternal(CallData *callData) const { Scope scope(engine()); ScopedContext context(scope, scope.engine->currentContext()); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 24e8b29e08..ac7aad3378 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -54,7 +54,7 @@ #include <private/qqmlpropertycache_p.h> #include <private/qintrusivelist_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> QT_BEGIN_NAMESPACE @@ -104,7 +104,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object QObject *object() const { return d()->object.data(); } - ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false); + ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false) const; static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0); static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value); @@ -128,7 +128,7 @@ private: QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const; - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); static PropertyAttributes query(const Managed *, String *name); static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes); @@ -149,17 +149,17 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject enum { DestroyMethod = -1, ToStringMethod = -2 }; static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const Value &qmlGlobal = Primitive::undefinedValue()); - static ReturnedValue create(QV4::ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue()); + static ReturnedValue create(QV4::ExecutionContext *scope, const QQmlValueTypeWrapper *valueType, int index, const Value &qmlGlobal = Primitive::undefinedValue()); int methodIndex() const { return d()->index; } QObject *object() const { return d()->object.data(); } - QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx); - QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc); + QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const; + QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const; - static ReturnedValue call(Managed *, CallData *callData); + static ReturnedValue call(const Managed *, CallData *callData); - ReturnedValue callInternal(CallData *callData); + ReturnedValue callInternal(CallData *callData) const; static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e); }; diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 8e18a5fbdd..715df2d666 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -34,7 +34,7 @@ #include "qv4regexp_p.h" #include "qv4engine_p.h" #include "qv4scopedvalue_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> using namespace QV4; diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index f6e88e62b7..3274e030c4 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -37,7 +37,7 @@ #include "qv4objectproto_p.h" #include "qv4regexp_p.h" #include "qv4stringobject_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4scopedvalue_p.h" #include <private/qqmljsengine_p.h> @@ -75,7 +75,7 @@ Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype) } Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global) - : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->regExpPrototype()) , value(value->d()) , global(global) { @@ -88,7 +88,7 @@ Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *valu // The conversion is not 100% exact since ECMA regexp and QRegExp // have different semantics/flags, but we try to do our best. Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re) - : Heap::Object(engine->emptyClass, engine->regExpPrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->regExpPrototype()) { value = 0; global = false; @@ -231,14 +231,14 @@ Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope) void Heap::RegExpCtor::clearLastMatch() { lastMatch = Primitive::nullValue(); - lastInput = internalClass->engine->id_empty; + lastInput = internalClass->engine->id_empty->d(); lastMatchStart = 0; lastMatchEnd = 0; } -ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) +ReturnedValue RegExpCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<Object *>(m)->engine()); + Scope scope(static_cast<const Object *>(m)->engine()); ScopedContext ctx(scope, scope.engine->currentContext()); ScopedValue r(scope, callData->argument(0)); @@ -286,7 +286,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) return Encode(ctx->d()->engine->newRegExpObject(regexp, global)); } -ReturnedValue RegExpCtor::call(Managed *that, CallData *callData) +ReturnedValue RegExpCtor::call(const Managed *that, CallData *callData) { if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) { if (callData->argc == 1 || callData->args[1].isUndefined()) @@ -300,7 +300,7 @@ void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e) { RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that); This->lastMatch.mark(e); - This->lastInput.mark(e); + This->lastInput->mark(e); FunctionObject::markObjects(that, e); } @@ -363,7 +363,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint)); const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets); - Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor); + Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor()); regExpCtor->d()->clearLastMatch(); if (result == -1) { @@ -372,7 +372,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) } // fill in result data - ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject())); + ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype())); int len = r->value()->captureCount(); array->arrayReserve(len); ScopedValue v(scope); @@ -388,7 +388,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) RegExpCtor::Data *dd = regExpCtor->d(); dd->lastMatch = array; - dd->lastInput = arg->stringValue(); + dd->lastInput = arg->stringValue()->d(); dd->lastMatchStart = matchOffsets[0]; dd->lastMatchEnd = matchOffsets[1]; @@ -425,7 +425,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx) ScopedCallData callData(scope, ctx->argc()); memcpy(callData->args, ctx->args(), ctx->argc()*sizeof(Value)); - Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData)); + Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor()->as<FunctionObject>()->construct(callData)); r->d()->value = re->value(); r->d()->global = re->global(); @@ -436,7 +436,7 @@ template <int index> ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) { Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch()); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch()); ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined()); if (result->isUndefined()) return ctx->d()->engine->newString()->asReturnedValue(); @@ -446,7 +446,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) { Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch()); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastMatch()); ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined()); if (result->isUndefined()) return ctx->d()->engine->newString()->asReturnedValue(); @@ -455,13 +455,13 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx) { - return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue(); + return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor())->lastInput()->asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor); + Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor()); QString lastInput = regExpCtor->lastInput()->toQString(); return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue(); } @@ -469,7 +469,7 @@ ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx) ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor); + Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor()); QString lastInput = regExpCtor->lastInput()->toQString(); return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index f5f255faf5..29d20614de 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -61,14 +61,14 @@ struct RegExpObject : Object { RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global); RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re); - RegExp *value; + Pointer<RegExp> value; bool global; }; struct RegExpCtor : FunctionObject { RegExpCtor(QV4::ExecutionContext *scope); Value lastMatch; - StringValue lastInput; + Pointer<String> lastInput; int lastMatchStart; int lastMatchEnd; void clearLastMatch(); @@ -117,12 +117,12 @@ struct RegExpCtor: FunctionObject V4_OBJECT2(RegExpCtor, FunctionObject) Value lastMatch() { return d()->lastMatch; } - StringValue lastInput() { return d()->lastInput; } + Heap::String *lastInput() { return d()->lastInput; } int lastMatchStart() { return d()->lastMatchStart; } int lastMatchEnd() { return d()->lastMatchEnd; } - static ReturnedValue construct(Managed *m, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); static void markObjects(Heap::Base *that, ExecutionEngine *e); }; @@ -146,7 +146,7 @@ struct RegExpPrototype: RegExpObject }; inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e) - : RegExpObject(e->emptyClass, e->objectPrototype.asObject()) + : RegExpObject(e->emptyClass, e->objectPrototype()) { } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index c31de6a9f0..b04d404ae4 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -40,6 +40,7 @@ #include "qv4stringobject_p.h" #include "qv4argumentsobject_p.h" #include "qv4objectiterator_p.h" +#include "qv4dateobject_p.h" #include "qv4lookup_p.h" #include "qv4function_p.h" #include "private/qlocale_tools_p.h" @@ -313,14 +314,14 @@ ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex) QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right) { Scope scope(engine); - ScopedFunctionObject f(scope, right.asFunctionObject()); + ScopedFunctionObject f(scope, right.as<FunctionObject>()); if (!f) return engine->throwTypeError(); if (f->isBoundFunction()) f = static_cast<BoundFunction *>(f.getPointer())->target(); - ScopedObject v(scope, left.asObject()); + ScopedObject v(scope, left.as<Object>()); if (!v) return Encode(false); @@ -380,10 +381,10 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n return engine->newString(qstr); } -ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint) +ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint) { if (typeHint == PREFERREDTYPE_HINT) { - if (object->asDateObject()) + if (object->as<DateObject>()) typeHint = STRING_HINT; else typeHint = NUMBER_HINT; @@ -401,10 +402,10 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint) Scope scope(engine); ScopedCallData callData(scope, 0); - callData->thisObject = object; + callData->thisObject = *object; ScopedValue conv(scope, object->get(*meth1)); - if (FunctionObject *o = conv->asFunctionObject()) { + if (FunctionObject *o = conv->as<FunctionObject>()) { ScopedValue r(scope, o->call(callData)); if (r->isPrimitive()) return r->asReturnedValue(); @@ -414,7 +415,7 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint) return Encode::undefined(); conv = object->get(*meth2); - if (FunctionObject *o = conv->asFunctionObject()) { + if (FunctionObject *o = conv->as<FunctionObject>()) { ScopedValue r(scope, o->call(callData)); if (r->isPrimitive()) return r->asReturnedValue(); @@ -575,7 +576,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object, ScopedObject o(scope, object); if (!o) { if (idx < UINT_MAX) { - if (String *str = object.asString()) { + if (const String *str = object.as<String>()) { if (idx >= (uint)str->toQString().length()) { return Encode::undefined(); } @@ -909,7 +910,7 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal return engine->throwTypeError(); ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]); - if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) + if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval)) return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true); return o->call(callData); @@ -931,7 +932,7 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI if (base) callData->thisObject = base; - FunctionObject *o = func->asFunctionObject(); + FunctionObject *o = func->as<FunctionObject>(); if (!o) { QString objectAsString = QStringLiteral("[null]"); if (base) @@ -940,7 +941,7 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI return engine->throwTypeError(msg); } - if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) { + if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval)) { return static_cast<EvalFunction *>(o)->evalCall(callData, true); } @@ -1034,7 +1035,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int if (scope.engine->hasException) return Encode::undefined(); - Object *f = func->asObject(); + Object *f = func->as<Object>(); if (!f) return engine->throwTypeError(); @@ -1043,7 +1044,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData) { - Object *f = func.asObject(); + const Object *f = func.as<Object>(); if (!f) return engine->throwTypeError(); @@ -1100,7 +1101,7 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value) case Value::Managed_Type: if (value.isString()) res = engine->id_string; - else if (value.objectValue()->asFunctionObject()) + else if (value.objectValue()->as<FunctionObject>()) res = engine->id_function; else res = engine->id_object; // ### implementation-defined @@ -1199,7 +1200,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value * { Scope scope(engine); QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId]; - ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype.asObject())); + ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype())); { bool needSparseArray = arrayGetterSetterCountAndFlags >> 30; @@ -1425,7 +1426,7 @@ void Runtime::convertThisToObject(ExecutionEngine *engine) if (t->isObject()) return; if (t->isNullOrUndefined()) { - *t = engine->globalObject()->asReturnedValue(); + *t = engine->globalObject->asReturnedValue(); } else { *t = t->toObject(engine)->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index f2f90bbc15..e8ebccc17b 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -34,8 +34,9 @@ #define QMLJS_RUNTIME_H #include "qv4global_p.h" -#include "qv4value_inl_p.h" +#include "qv4value_p.h" #include "qv4context_p.h" +#include "qv4engine_p.h" #include "qv4math_p.h" #include <QtCore/qnumeric.h> @@ -218,7 +219,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime { }; struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { - static ReturnedValue objectDefaultValue(Object *object, int typeHint); + static ReturnedValue objectDefaultValue(const Object *object, int typeHint); static ReturnedValue toPrimitive(const Value &value, int typeHint); static double stringToNumber(const QString &s); @@ -243,7 +244,7 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { #ifndef V4_BOOTSTRAP inline ReturnedValue RuntimeHelpers::toPrimitive(const Value &value, int typeHint) { - Object *o = value.asObject(); + const Object *o = value.as<Object>(); if (!o) return value.asReturnedValue(); return RuntimeHelpers::objectDefaultValue(o, typeHint); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 908248f0f0..98ced91b05 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -85,10 +85,7 @@ struct Scope { #ifndef QT_NO_DEBUG size += nValues; #endif - Value *ptr = engine->jsStackTop; - engine->jsStackTop = ptr + nValues; - memset(ptr, 0, nValues*sizeof(Value)); - return ptr; + return engine->jsAlloca(nValues); } bool hasException() const { @@ -202,7 +199,7 @@ struct Scoped { enum _Convert { Convert }; - inline void setPointer(Managed *p) { + inline void setPointer(const Managed *p) { ptr->m = p ? p->m : 0; #if QT_POINTER_SIZE == 4 ptr->tag = QV4::Value::Managed_Type; @@ -225,7 +222,7 @@ struct Scoped Scoped(const Scope &scope, const Value &v) { ptr = scope.engine->jsStackTop++; - setPointer(value_cast<T>(v)); + setPointer(v.as<T>()); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -235,7 +232,7 @@ struct Scoped Value v; v = o; ptr = scope.engine->jsStackTop++; - setPointer(value_cast<T>(v)); + setPointer(v.as<T>()); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -243,7 +240,7 @@ struct Scoped Scoped(const Scope &scope, const ScopedValue &v) { ptr = scope.engine->jsStackTop++; - setPointer(value_cast<T>(*v.ptr)); + setPointer(v.ptr->as<T>()); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -261,7 +258,7 @@ struct Scoped Scoped(const Scope &scope, const Value *v) { ptr = scope.engine->jsStackTop++; - setPointer(v ? value_cast<T>(*v) : 0); + setPointer(v ? v->as<T>() : 0); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -287,7 +284,7 @@ struct Scoped Scoped(const Scope &scope, const ReturnedValue &v) { ptr = scope.engine->jsStackTop++; - setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v))); + setPointer(QV4::Value::fromReturnedValue(v).as<T>()); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -302,9 +299,7 @@ struct Scoped } Scoped<T> &operator=(Heap::Base *o) { - Value v; - v = o; - setPointer(value_cast<T>(v)); + setPointer(Value::fromHeapObject(o).as<T>()); return *this; } Scoped<T> &operator=(typename T::Data *t) { @@ -312,16 +307,16 @@ struct Scoped return *this; } Scoped<T> &operator=(const Value &v) { - setPointer(value_cast<T>(v)); + setPointer(v.as<T>()); return *this; } Scoped<T> &operator=(Value *v) { - setPointer(v ? value_cast<T>(*v) : 0); + setPointer(v ? v->as<T>() : 0); return *this; } Scoped<T> &operator=(const ReturnedValue &v) { - setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v))); + setPointer(QV4::Value::fromReturnedValue(v).as<T>()); return *this; } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 4fde0e2445..bd5529294c 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -32,7 +32,7 @@ ****************************************************************************/ #include "qv4script_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4functionobject_p.h" #include "qv4function_p.h" #include "qv4context_p.h" @@ -122,13 +122,13 @@ Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Ob s.engine->popContext(); } -ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *) +ReturnedValue QmlBindingWrapper::call(const Managed *that, CallData *) { - ExecutionEngine *engine = static_cast<Object *>(that)->engine(); + ExecutionEngine *engine = static_cast<const Object *>(that)->engine(); CHECK_STACK_LIMITS(engine); Scope scope(engine); - QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that); + const QmlBindingWrapper *This = static_cast<const QmlBindingWrapper *>(that); if (!This->function()) return QV4::Encode::undefined(); @@ -154,7 +154,7 @@ void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e) static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex) { QV4::Scope scope(ctx); - QV4::Scoped<CallContext> signalEmittingContext(scope, static_cast<Heap::CallContext *>(ctx->d()->parent)); + QV4::Scoped<CallContext> signalEmittingContext(scope, ctx->d()->parent.cast<Heap::CallContext>()); Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext); return signalEmittingContext->argument(parameterIndex); } diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 05a9e45f45..998a2cff72 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -90,8 +90,8 @@ struct QmlBindingWrapper : Heap::FunctionObject { QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml); // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable! QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml); - Object *qml; - CallContext *qmlContext; + Pointer<Object> qml; + Pointer<CallContext> qmlContext; }; } @@ -99,15 +99,13 @@ struct QmlBindingWrapper : Heap::FunctionObject { struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject { V4_OBJECT2(QmlBindingWrapper, FunctionObject) - static ReturnedValue call(Managed *that, CallData *); + static ReturnedValue call(const Managed *that, CallData *); static void markObjects(Heap::Base *m, ExecutionEngine *e); Heap::CallContext *context() const { return d()->qmlContext; } static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction, const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0); - -private: }; struct Q_QML_EXPORT Script { diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index f1f546bece..cd66f2942b 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -175,7 +175,7 @@ template <> QUrl convertValueToElement(const Value &value) template <> QModelIndex convertValueToElement(const Value &value) { - const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value); + const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>(); if (v) return v->toVariant().toModelIndex(); return QModelIndex(); @@ -183,7 +183,7 @@ template <> QModelIndex convertValueToElement(const Value &value) template <> QItemSelectionRange convertValueToElement(const Value &value) { - const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value); + const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>(); if (v) return v->toVariant().value<QItemSelectionRange>(); return QItemSelectionRange(); @@ -231,7 +231,7 @@ public: defineAccessorProperty(QStringLiteral("length"), method_get_length, method_set_length); } - QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) + QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) const { /* Qt containers have int (rather than uint) allowable indexes. */ if (index > INT_MAX) { @@ -400,7 +400,7 @@ public: ScopedCallData callData(scope, 2); callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs); callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs); - callData->thisObject = this->m_ctx->d()->engine->globalObject(); + callData->thisObject = this->m_ctx->d()->engine->globalObject; QV4::ScopedValue result(scope, compare->call(callData)); return result->toNumber() < 0; } @@ -419,7 +419,7 @@ public: } QV4::Scope scope(ctx); - if (ctx->argc() == 1 && ctx->args()[0].asFunctionObject()) { + if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) { CompareFunctor cf(ctx, ctx->args()[0]); std::sort(d()->container.begin(), d()->container.end(), cf); } else { @@ -526,8 +526,8 @@ public: QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a); } - static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty) - { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); } + static QV4::ReturnedValue getIndexed(const QV4::Managed *that, uint index, bool *hasProperty) + { return static_cast<const QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); } static void putIndexed(Managed *that, uint index, const QV4::Value &value) { static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); } static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index) @@ -544,7 +544,7 @@ public: template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container) - : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->sequencePrototype()) , container(container) , propertyIndex(-1) , isReference(false) @@ -557,7 +557,7 @@ Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex) - : Heap::Object(engine->emptyClass, engine->sequencePrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->sequencePrototype()) , object(object) , propertyIndex(propertyIndex) , isReference(true) @@ -700,11 +700,11 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo { *succeeded = true; - if (!array.asArrayObject()) { + if (!array.as<ArrayObject>()) { *succeeded = false; return QVariant(); } - QV4::Scope scope(array.asObject()->engine()); + QV4::Scope scope(array.as<Object>()->engine()); QV4::ScopedArrayObject a(scope, array); FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); } @@ -717,7 +717,7 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo return qMetaTypeId<SequenceType>(); \ } else -int SequencePrototype::metaTypeForSequence(QV4::Object *object) +int SequencePrototype::metaTypeForSequence(const QV4::Object *object) { FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE) /*else*/ { diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index 9949278a89..560c3c27ca 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -48,9 +48,10 @@ #include <QtCore/qglobal.h> #include <QtCore/qvariant.h> -#include "qv4value_inl_p.h" +#include "qv4value_p.h" #include "qv4object_p.h" #include "qv4context_p.h" +#include "qv4string_p.h" QT_BEGIN_NAMESPACE @@ -70,7 +71,7 @@ struct SequencePrototype : public QV4::Object static bool isSequenceType(int sequenceTypeId); static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded); static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded); - static int metaTypeForSequence(Object *object); + static int metaTypeForSequence(const Object *object); static QVariant toVariant(Object *object); static QVariant toVariant(const Value &array, int typeHint, bool *succeeded); }; diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index e669924d4a..d98c1cc341 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -37,7 +37,7 @@ #include <private/qqmllistmodel_p.h> #include <private/qqmllistmodelworkeragent_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4dateobject_p.h> #include <private/qv4regexpobject_p.h> #include <private/qv4sequenceobject_p.h> @@ -168,11 +168,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine char *buffer = data.data() + offset; memcpy(buffer, qstr.constData(), length*sizeof(QChar)); - } else if (v.asFunctionObject()) { + } else if (v.as<FunctionObject>()) { // XXX TODO: Implement passing function objects between the main and // worker scripts push(data, valueheader(WorkerUndefined)); - } else if (QV4::ArrayObject *array = v.asArrayObject()) { + } else if (const QV4::ArrayObject *array = v.as<ArrayObject>()) { uint length = array->getLength(); if (length > 0xFFFFFF) { push(data, valueheader(WorkerUndefined)); @@ -195,11 +195,11 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine reserve(data, sizeof(quint32) + sizeof(double)); push(data, valueheader(WorkerNumber)); push(data, v.asDouble()); - } else if (QV4::DateObject *d = v.asDateObject()) { + } else if (const QV4::DateObject *d = v.as<DateObject>()) { reserve(data, sizeof(quint32) + sizeof(double)); push(data, valueheader(WorkerDate)); - push(data, d->date().asDouble()); - } else if (RegExpObject *re = v.as<RegExpObject>()) { + push(data, d->date()); + } else if (const RegExpObject *re = v.as<RegExpObject>()) { quint32 flags = re->flags(); QString pattern = re->source(); int length = pattern.length() + 1; @@ -218,7 +218,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine char *buffer = data.data() + offset; memcpy(buffer, pattern.constData(), length*sizeof(QChar)); - } else if (QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) { + } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) { // XXX TODO: Generalize passing objects between the main thread and worker scripts so // that others can trivially plug in their elements. QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object()); @@ -231,7 +231,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine } // No other QObject's are allowed to be sent push(data, valueheader(WorkerUndefined)); - } else if (Object *o = v.asObject()) { + } else if (const Object *o = v.as<Object>()) { if (o->isListType()) { // valid sequence. we generate a length (sequence length + 1 for the sequence type) uint seqLength = ScopedValue(scope, o->get(engine->id_length))->toUInt32(); @@ -265,7 +265,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine s = properties->getIndexed(ii); serialize(data, s, engine); - QV4::String *str = s->asString(); + QV4::String *str = s->as<String>(); val = o->get(str); if (scope.hasException()) scope.engine->catchException(); @@ -356,7 +356,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) QVariant var = qVariantFromValue(ref); QV4::ScopedValue v(scope, scope.engine->fromVariant(var)); QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref"))); - rv->asObject()->defineReadonlyProperty(s, v); + rv->as<Object>()->defineReadonlyProperty(s, v); agent->release(); agent->setEngine(engine); diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h index 06eaffe4c4..d5d48edee7 100644 --- a/src/qml/jsruntime/qv4serialize_p.h +++ b/src/qml/jsruntime/qv4serialize_p.h @@ -46,7 +46,7 @@ // #include <QtCore/qbytearray.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h index 861c7dd28d..8496fc32e7 100644 --- a/src/qml/jsruntime/qv4sparsearray_p.h +++ b/src/qml/jsruntime/qv4sparsearray_p.h @@ -35,11 +35,7 @@ #define QV4SPARSEARRAY_H #include "qv4global_p.h" -#include <QtCore/qmap.h> -#include "qv4value_inl_p.h" -#include "qv4scopedvalue_p.h" -#include "qv4property_p.h" -#include <assert.h> +#include <QtCore/qlist.h> //#define Q_MAP_DEBUG #ifdef Q_MAP_DEBUG @@ -188,7 +184,7 @@ public: typedef qptrdiff difference_type; typedef int size_type; -#ifndef QT_NO_DEBUG +#ifdef Q_MAP_DEBUG void dump() const; #endif }; @@ -261,7 +257,7 @@ inline void SparseArray::push_back(uint index, uint len) n->value = index; } -#ifndef QT_NO_DEBUG +#ifdef Q_MAP_DEBUG inline void SparseArray::dump() const { const SparseArrayNode *it = begin(); @@ -344,4 +340,4 @@ inline SparseArrayNode *SparseArray::upperBound(uint akey) QT_END_NAMESPACE -#endif // QMAP_H +#endif diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 20dd84420c..cf013121b1 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -32,7 +32,7 @@ ****************************************************************************/ #include "qv4string_p.h" -#include "qv4value_inl_p.h" +#include "qv4value_p.h" #ifndef V4_BOOTSTRAP #include "qv4identifiertable_p.h" #include "qv4runtime_p.h" diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 5a0c83b4b9..b133f68b20 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -184,6 +184,20 @@ public: static uint toArrayIndex(const QString &str); }; +template<> +inline const String *Value::as() const { + return isManaged() && m && m->vtable->isString ? static_cast<const String *>(this) : 0; +} + +#ifndef V4_BOOTSTRAP +template<> +inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v) +{ + return v.toString(e)->asReturnedValue(); +} +#endif + + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index e0b84f6da3..bbdc96f0f1 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -36,7 +36,7 @@ #include "qv4regexp_p.h" #include "qv4regexpobject_p.h" #include "qv4objectproto_p.h" -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #include "qv4scopedvalue_p.h" #include "qv4alloca_p.h" #include <QtCore/QDateTime> @@ -80,7 +80,7 @@ Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype) } Heap::StringObject::StringObject(ExecutionEngine *engine, const Value &val) - : Heap::Object(engine->emptyClass, engine->stringPrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->stringPrototype()) { value = val; Q_ASSERT(value.isString()); @@ -104,7 +104,7 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index) { ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine(); Scope scope(v4); - Scoped<StringObject> o(scope, m->asStringObject()); + Scoped<StringObject> o(scope, m->as<StringObject>()); Q_ASSERT(!!o); if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) { @@ -158,9 +158,9 @@ Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope) { } -ReturnedValue StringCtor::construct(Managed *m, CallData *callData) +ReturnedValue StringCtor::construct(const Managed *m, CallData *callData) { - ExecutionEngine *v4 = static_cast<Object *>(m)->engine(); + ExecutionEngine *v4 = static_cast<const Object *>(m)->engine(); Scope scope(v4); ScopedValue value(scope); if (callData->argc) @@ -170,9 +170,9 @@ ReturnedValue StringCtor::construct(Managed *m, CallData *callData) return Encode(v4->newStringObject(value)); } -ReturnedValue StringCtor::call(Managed *m, CallData *callData) +ReturnedValue StringCtor::call(const Managed *m, CallData *callData) { - ExecutionEngine *v4 = static_cast<Object *>(m)->engine(); + ExecutionEngine *v4 = static_cast<const Object *>(m)->engine(); Scope scope(v4); ScopedValue value(scope); if (callData->argc) @@ -220,7 +220,7 @@ static QString getThisString(ExecutionContext *ctx) ScopedValue t(scope, ctx->thisObject()); if (t->isString()) return t->stringValue()->toQString(); - if (StringObject *thisString = t->asStringObject()) + if (StringObject *thisString = t->as<StringObject>()) return thisString->d()->value.stringValue()->toQString(); if (t->isUndefined() || t->isNull()) { scope.engine->throwTypeError(); @@ -234,7 +234,7 @@ ReturnedValue StringPrototype::method_toString(CallContext *context) if (context->thisObject().isString()) return context->thisObject().asReturnedValue(); - StringObject *o = context->thisObject().asStringObject(); + StringObject *o = context->thisObject().as<StringObject>(); if (!o) return context->engine()->throwTypeError(); return o->d()->value.asReturnedValue(); @@ -368,7 +368,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context) if (!rx) { ScopedCallData callData(scope, 1); callData->args[0] = regexp; - rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData); + rx = context->d()->engine->regExpCtor()->construct(callData); } if (!rx) @@ -379,7 +379,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context) // ### use the standard builtin function, not the one that might be redefined in the proto ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec"))); - ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString)); + ScopedFunctionObject exec(scope, scope.engine->regExpPrototype()->get(execString)); ScopedCallData callData(scope, 1); callData->thisObject = rx; @@ -470,7 +470,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) { Scope scope(ctx); QString string; - if (StringObject *thisString = ctx->thisObject().asStringObject()) + if (StringObject *thisString = ctx->thisObject().as<StringObject>()) string = thisString->d()->value.stringValue()->toQString(); else string = ctx->thisObject().toQString(); @@ -593,7 +593,7 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) if (!regExp) { ScopedCallData callData(scope, 1); callData->args[0] = regExpValue; - regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData); + regExpValue = ctx->d()->engine->regExpCtor()->construct(callData); if (scope.engine->hasException) return Encode::undefined(); regExp = regExpValue->as<RegExpObject>(); diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 459dc1322e..b0f2dd3e97 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -78,8 +78,8 @@ struct StringCtor: FunctionObject { V4_OBJECT2(StringCtor, FunctionObject) - static ReturnedValue construct(Managed *m, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; struct StringPrototype: StringObject diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 429ec96f0b..d93b57e472 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qv4typedarray_p.h" #include "qv4arraybuffer_p.h" +#include "qv4string_p.h" #include <cmath> @@ -201,10 +202,10 @@ Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::T { } -ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData) +ReturnedValue TypedArrayCtor::construct(const Managed *m, CallData *callData) { - Scope scope(static_cast<Object *>(m)->engine()); - Scoped<TypedArrayCtor> that(scope, static_cast<TypedArrayCtor *>(m)); + Scope scope(static_cast<const Object *>(m)->engine()); + Scoped<TypedArrayCtor> that(scope, static_cast<const TypedArrayCtor *>(m)); if (!callData->argc || !callData->args[0].isObject()) { // ECMA 6 22.2.1.1 @@ -329,13 +330,13 @@ ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData) return array.asReturnedValue(); } -ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData) +ReturnedValue TypedArrayCtor::call(const Managed *that, CallData *callData) { return construct(that, callData); } Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t) - : Heap::Object(e->emptyClass, e->typedArrayPrototype[t].asObject()), + : Heap::Object(e->emptyClass, e->typedArrayPrototype + t), type(operations + t), arrayType(t) { @@ -347,10 +348,10 @@ void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e) Object::markObjects(that, e); } -ReturnedValue TypedArray::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue TypedArray::getIndexed(const Managed *m, uint index, bool *hasProperty) { - Scope scope(static_cast<Object *>(m)->engine()); - Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m)); + Scope scope(static_cast<const Object *>(m)->engine()); + Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m)); uint bytesPerElement = a->d()->type->bytesPerElement; uint byteOffset = a->d()->byteOffset + index * bytesPerElement; diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index afd1bb97e7..8e1090dcd2 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -72,7 +72,7 @@ struct TypedArray : Object { TypedArray(ExecutionEngine *e, Type t); const TypedArrayOperations *type; - ArrayBuffer *buffer; + Pointer<ArrayBuffer> buffer; uint byteLength; uint byteOffset; Type arrayType; @@ -113,7 +113,7 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object } static void markObjects(Heap::Base *that, ExecutionEngine *e); - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); static void putIndexed(Managed *m, uint index, const Value &value); }; @@ -121,8 +121,8 @@ struct TypedArrayCtor: FunctionObject { V4_OBJECT2(TypedArrayCtor, FunctionObject) - static ReturnedValue construct(Managed *m, CallData *callData); - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue construct(const Managed *m, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); }; diff --git a/src/qml/qml/qqmlabstractexpression.cpp b/src/qml/jsruntime/qv4typedvalue_p.h index c55c86952c..50b5a4db81 100644 --- a/src/qml/qml/qqmlabstractexpression.cpp +++ b/src/qml/jsruntime/qv4typedvalue_p.h @@ -30,64 +30,46 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef QV4TYPEDVALUE_H +#define QV4TYPEDVALUE_H -#include "qqmlabstractexpression_p.h" +#include "qv4value_p.h" QT_BEGIN_NAMESPACE -QQmlAbstractExpression::QQmlAbstractExpression() -: m_prevExpression(0), m_nextExpression(0) -{ -} +namespace QV4 { -QQmlAbstractExpression::~QQmlAbstractExpression() +template <typename T> +struct TypedValue : public Value { - if (m_prevExpression) { - *m_prevExpression = m_nextExpression; - if (m_nextExpression) - m_nextExpression->m_prevExpression = m_prevExpression; + template<typename X> + TypedValue &operator =(X *x) { + m = x; +#if QT_POINTER_SIZE == 4 + tag = Managed_Type; +#endif + return *this; } + TypedValue &operator =(T *t); + TypedValue &operator =(const Scoped<T> &v); +// TypedValue &operator =(const ManagedRef<T> &v); - if (m_context.isT2()) - m_context.asT2()->_s = 0; -} - -QQmlContextData *QQmlAbstractExpression::context() const -{ - if (m_context.isT1()) return m_context.asT1(); - else return m_context.asT2()->_c; -} + TypedValue &operator =(const TypedValue<T> &t); -void QQmlAbstractExpression::setContext(QQmlContextData *context) -{ - if (m_prevExpression) { - *m_prevExpression = m_nextExpression; - if (m_nextExpression) - m_nextExpression->m_prevExpression = m_prevExpression; - m_prevExpression = 0; - m_nextExpression = 0; - } + bool operator!() const { return !managed(); } - if (m_context.isT1()) m_context = context; - else m_context.asT2()->_c = context; + operator T *() { return static_cast<T *>(managed()); } + T *operator->() { return static_cast<T *>(managed()); } + const T *operator->() const { return static_cast<T *>(managed()); } + T *getPointer() const { return static_cast<T *>(managed()); } - if (context) { - m_nextExpression = context->expressions; - if (m_nextExpression) - m_nextExpression->m_prevExpression = &m_nextExpression; - m_prevExpression = &context->expressions; - context->expressions = this; - } -} + void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); } +}; +typedef TypedValue<String> StringValue; -void QQmlAbstractExpression::refresh() -{ -} -bool QQmlAbstractExpression::isValid() const -{ - return context() != 0; -} +} // namespace QV4 QT_END_NAMESPACE +#endif diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index 68228f06bb..d659d02c3b 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -32,10 +32,11 @@ ****************************************************************************/ #include <qv4engine_p.h> #include <qv4runtime_p.h> +#include <qv4string_p.h> #ifndef V4_BOOTSTRAP #include <qv4object_p.h> #include <qv4objectproto_p.h> -#include "qv4mm_p.h" +#include <private/qv4mm_p.h> #endif #include <wtf/MathExtras.h> @@ -68,6 +69,28 @@ int Value::toUInt16() const return (unsigned short)number; } +bool Value::toBoolean() const +{ + switch (type()) { + case Value::Undefined_Type: + case Value::Null_Type: + return false; + case Value::Boolean_Type: + case Value::Integer_Type: + return (bool)int_32; + case Value::Managed_Type: +#ifdef V4_BOOTSTRAP + Q_UNIMPLEMENTED(); +#else + if (isString()) + return stringValue()->toQString().length() > 0; +#endif + return true; + default: // double + return doubleValue() && !std::isnan(doubleValue()); + } +} + double Value::toInteger() const { if (integerCompatible()) @@ -87,10 +110,10 @@ double Value::toNumberImpl() const #else if (isString()) return RuntimeHelpers::stringToNumber(stringValue()->toQString()); - { - Q_ASSERT(isObject()); - Scope scope(objectValue()->engine()); - ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT)); + { + Q_ASSERT(isObject()); + Scope scope(objectValue()->engine()); + ScopedValue prim(scope, RuntimeHelpers::toPrimitive(*this, NUMBER_HINT)); if (scope.engine->hasException) return 0; return prim->toNumber(); @@ -281,4 +304,35 @@ Heap::Object *Value::toObject(ExecutionEngine *e) const return RuntimeHelpers::convertToObject(e, *this); } +uint Value::asArrayLength(bool *ok) const +{ + *ok = true; + if (isInteger()) { + if (int_32 >= 0) { + return (uint)int_32; + } else { + *ok = false; + return UINT_MAX; + } + } + if (isNumber()) { + double d = doubleValue(); + uint idx = (uint)d; + if (idx != d) { + *ok = false; + return UINT_MAX; + } + return idx; + } + if (isString()) + return stringValue()->toUInt(ok); + + uint idx = toUInt32(); + double d = toNumber(); + if (d != idx) { + *ok = false; + return UINT_MAX; + } + return idx; +} #endif // V4_BOOTSTRAP diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h deleted file mode 100644 index 3a4c5c4822..0000000000 --- a/src/qml/jsruntime/qv4value_inl_p.h +++ /dev/null @@ -1,293 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QV4VALUE_INL_H -#define QV4VALUE_INL_H - -#include <cmath> // this HAS to come - -#include "qv4value_p.h" - -#include "qv4string_p.h" -#include "qv4managed_p.h" -#include "qv4engine_p.h" - -QT_BEGIN_NAMESPACE - -namespace QV4 { - -inline bool Value::isString() const -{ - if (!isManaged()) - return false; - return m && m->vtable->isString; -} -inline bool Value::isObject() const -{ - if (!isManaged()) - return false; - return m && m->vtable->isObject; -} - -inline bool Value::isPrimitive() const -{ - return !isObject(); -} - -inline String *Value::asString() const -{ - if (isString()) - return stringValue(); - return 0; -} - -inline void Value::mark(ExecutionEngine *e) const -{ - if (!val) - return; - Managed *m = asManaged(); - if (m) - m->mark(e); -} - -inline Primitive Primitive::nullValue() -{ - Primitive v; -#if QT_POINTER_SIZE == 8 - v.val = quint64(_Null_Type) << Tag_Shift; -#else - v.tag = _Null_Type; - v.int_32 = 0; -#endif - return v; -} - -inline Primitive Primitive::fromBoolean(bool b) -{ - Primitive v; - v.tag = _Boolean_Type; - v.int_32 = (bool)b; - return v; -} - -inline Primitive Primitive::fromDouble(double d) -{ - Primitive v; - v.setDouble(d); - return v; -} - -inline Primitive Primitive::fromInt32(int i) -{ - Primitive v; - v.tag = _Integer_Type; - v.int_32 = i; - return v; -} - -inline Primitive Primitive::fromUInt32(uint i) -{ - Primitive v; - if (i < INT_MAX) { - v.tag = _Integer_Type; - v.int_32 = (int)i; - } else { - v.setDouble(i); - } - return v; -} - -inline double Value::toNumber() const -{ - if (isInteger()) - return int_32; - if (isDouble()) - return doubleValue(); - return toNumberImpl(); -} - -inline int Value::toInt32() const -{ - if (isInteger()) - return int_32; - double d = isNumber() ? doubleValue() : toNumberImpl(); - - const double D32 = 4294967296.0; - const double D31 = D32 / 2.0; - - if ((d >= -D31 && d < D31)) - return static_cast<int>(d); - - return Primitive::toInt32(d); -} - -inline unsigned int Value::toUInt32() const -{ - return (unsigned int)toInt32(); -} - - -inline bool Value::toBoolean() const -{ - switch (type()) { - case Value::Undefined_Type: - case Value::Null_Type: - return false; - case Value::Boolean_Type: - case Value::Integer_Type: - return (bool)int_32; - case Value::Managed_Type: -#ifdef V4_BOOTSTRAP - Q_UNIMPLEMENTED(); -#else - if (isString()) - return stringValue()->toQString().length() > 0; -#endif - return true; - default: // double - return doubleValue() && !std::isnan(doubleValue()); - } -} - -#ifndef V4_BOOTSTRAP -inline uint Value::asArrayIndex() const -{ -#if QT_POINTER_SIZE == 8 - if (!isNumber()) - return UINT_MAX; - if (isInteger()) - return int_32 >= 0 ? (uint)int_32 : UINT_MAX; -#else - if (isInteger() && int_32 >= 0) - return (uint)int_32; - if (!isDouble()) - return UINT_MAX; -#endif - double d = doubleValue(); - uint idx = (uint)d; - if (idx != d) - return UINT_MAX; - return idx; -} - -inline uint Value::asArrayLength(bool *ok) const -{ - *ok = true; - if (isInteger()) { - if (int_32 >= 0) { - return (uint)int_32; - } else { - *ok = false; - return UINT_MAX; - } - } - if (isNumber()) { - double d = doubleValue(); - uint idx = (uint)d; - if (idx != d) { - *ok = false; - return UINT_MAX; - } - return idx; - } - if (isString()) - return stringValue()->toUInt(ok); - - uint idx = toUInt32(); - double d = toNumber(); - if (d != idx) { - *ok = false; - return UINT_MAX; - } - return idx; -} - -inline Object *Value::asObject() const -{ - return isObject() ? objectValue() : 0; -} - -inline FunctionObject *Value::asFunctionObject() const -{ - return isObject() ? managed()->asFunctionObject() : 0; -} - -inline NumberObject *Value::asNumberObject() const -{ - return isObject() ? managed()->asNumberObject() : 0; -} - -inline StringObject *Value::asStringObject() const -{ - return isObject() ? managed()->asStringObject() : 0; -} - -inline DateObject *Value::asDateObject() const -{ - return isObject() ? managed()->asDateObject() : 0; -} - -inline ArrayObject *Value::asArrayObject() const -{ - return isObject() ? managed()->asArrayObject() : 0; -} - -inline ErrorObject *Value::asErrorObject() const -{ - return isObject() ? managed()->asErrorObject() : 0; -} - -template<typename T> -inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; } - -#ifndef V4_BOOTSTRAP - -template<> -inline String *value_cast(const Value &v) { - return v.asString(); -} - -template<> -inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v) -{ - return v.toString(e)->asReturnedValue(); -} - -#endif - -#endif - -} // namespace QV4 - -QT_END_NAMESPACE - -#endif diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index cd1aef86d7..7454cbfff4 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -37,61 +37,18 @@ #include <QtCore/QString> #include "qv4global_p.h" +#include <private/qv4heap_p.h> QT_BEGIN_NAMESPACE namespace QV4 { -typedef uint Bool; - namespace Heap { - -struct Q_QML_EXPORT Base { - union { - const ManagedVTable *vtable; - quintptr mm_data; - }; - - inline ReturnedValue asReturnedValue() const; - inline void mark(QV4::ExecutionEngine *engine); - - enum { - MarkBit = 0x1, - NotInUse = 0x2, - PointerMask = ~0x3 - }; - - ManagedVTable *gcGetVtable() const { - return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask); - } - inline bool isMarked() const { - return mm_data & MarkBit; - } - inline void setMarkBit() { - mm_data |= MarkBit; - } - inline void clearMarkBit() { - mm_data &= ~MarkBit; - } - - inline bool inUse() const { - return !(mm_data & NotInUse); - } - - Base *nextFree() { - return reinterpret_cast<Base *>(mm_data & PointerMask); - } - void setNextFree(Base *m) { - mm_data = (reinterpret_cast<quintptr>(m) | NotInUse); - } - - void *operator new(size_t, Managed *m) { return m; } - void *operator new(size_t, Heap::Base *m) { return m; } - void operator delete(void *, Heap::Base *) {} -}; - + struct Base; } +typedef uint Bool; + struct Q_QML_PRIVATE_EXPORT Value { /* @@ -326,13 +283,11 @@ struct Q_QML_PRIVATE_EXPORT Value return v; } - static inline Value fromManaged(Managed *m); - int toUInt16() const; inline int toInt32() const; inline unsigned int toUInt32() const; - inline bool toBoolean() const; + bool toBoolean() const; double toInteger() const; inline double toNumber() const; double toNumberImpl() const; @@ -349,17 +304,28 @@ struct Q_QML_PRIVATE_EXPORT Value return b; } - inline String *asString() const; - inline Managed *asManaged() const; - inline Object *asObject() const; - inline FunctionObject *asFunctionObject() const; - inline NumberObject *asNumberObject() const; - inline StringObject *asStringObject() const; - inline DateObject *asDateObject() const; - inline ArrayObject *asArrayObject() const; - inline ErrorObject *asErrorObject() const; + template <typename T> + const T *as() const { + if (!m || !isManaged()) + return 0; + + Q_ASSERT(m->vtable); +#if !defined(QT_NO_QOBJECT_CHECK) + static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this)); +#endif + const VTable *vt = m->vtable; + while (vt) { + if (vt == T::staticVTable()) + return static_cast<const T *>(this); + vt = vt->parent; + } + return 0; + } + template <typename T> + T *as() { + return const_cast<T *>(const_cast<const Value *>(this)->as<T>()); + } - template<typename T> inline T *as() const; template<typename T> inline T *cast() { return static_cast<T *>(managed()); } @@ -368,7 +334,9 @@ struct Q_QML_PRIVATE_EXPORT Value } inline uint asArrayIndex() const; - inline uint asArrayLength(bool *ok) const; +#ifndef V4_BOOTSTRAP + uint asArrayLength(bool *ok) const; +#endif ReturnedValue asReturnedValue() const { return val; } static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; } @@ -376,12 +344,17 @@ struct Q_QML_PRIVATE_EXPORT Value // Section 9.12 bool sameValue(Value other) const; - inline void mark(ExecutionEngine *e) const; + inline void mark(ExecutionEngine *e); Value &operator =(const ScopedValue &v); Value &operator=(ReturnedValue v) { val = v; return *this; } Value &operator=(Managed *m) { - val = Value::fromManaged(m).val; + if (!m) { + tag = Undefined_Type; + uint_32 = 0; + } else { + val = reinterpret_cast<Value *>(m)->val; + } return *this; } Value &operator=(Heap::Base *o) { @@ -400,13 +373,64 @@ struct Q_QML_PRIVATE_EXPORT Value } }; -inline Managed *Value::asManaged() const +inline bool Value::isString() const +{ + if (!isManaged()) + return false; + return m && m->vtable->isString; +} +inline bool Value::isObject() const +{ + if (!isManaged()) + return false; + return m && m->vtable->isObject; +} + +inline bool Value::isPrimitive() const +{ + return !isObject(); +} + +inline double Value::toNumber() const +{ + if (isInteger()) + return int_32; + if (isDouble()) + return doubleValue(); + return toNumberImpl(); +} + + +#ifndef V4_BOOTSTRAP +inline uint Value::asArrayIndex() const +{ +#if QT_POINTER_SIZE == 8 + if (!isNumber()) + return UINT_MAX; + if (isInteger()) + return int_32 >= 0 ? (uint)int_32 : UINT_MAX; +#else + if (isInteger() && int_32 >= 0) + return (uint)int_32; + if (!isDouble()) + return UINT_MAX; +#endif + double d = doubleValue(); + uint idx = (uint)d; + if (idx != d) + return UINT_MAX; + return idx; +} +#endif + +inline +ReturnedValue Heap::Base::asReturnedValue() const { - if (isManaged()) - return managed(); - return 0; + return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue(); } + + struct Q_QML_PRIVATE_EXPORT Primitive : public Value { inline static Primitive emptyValue(); @@ -445,34 +469,52 @@ inline Primitive Primitive::emptyValue() return v; } -template <typename T> -struct TypedValue : public Value +inline Primitive Primitive::nullValue() { - template<typename X> - TypedValue &operator =(X *x) { - m = x; -#if QT_POINTER_SIZE == 4 - tag = Managed_Type; + Primitive v; +#if QT_POINTER_SIZE == 8 + v.val = quint64(_Null_Type) << Tag_Shift; +#else + v.tag = _Null_Type; + v.int_32 = 0; #endif - return *this; - } - TypedValue &operator =(T *t); - TypedValue &operator =(const Scoped<T> &v); -// TypedValue &operator =(const ManagedRef<T> &v); - - TypedValue &operator =(const TypedValue<T> &t); + return v; +} - bool operator!() const { return !managed(); } +inline Primitive Primitive::fromBoolean(bool b) +{ + Primitive v; + v.tag = _Boolean_Type; + v.int_32 = (bool)b; + return v; +} - operator T *() { return static_cast<T *>(managed()); } - T *operator->() { return static_cast<T *>(managed()); } - const T *operator->() const { return static_cast<T *>(managed()); } - T *getPointer() const { return static_cast<T *>(managed()); } +inline Primitive Primitive::fromDouble(double d) +{ + Primitive v; + v.setDouble(d); + return v; +} - void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); } -}; -typedef TypedValue<String> StringValue; +inline Primitive Primitive::fromInt32(int i) +{ + Primitive v; + v.tag = _Integer_Type; + v.int_32 = i; + return v; +} +inline Primitive Primitive::fromUInt32(uint i) +{ + Primitive v; + if (i < INT_MAX) { + v.tag = _Integer_Type; + v.int_32 = (int)i; + } else { + v.setDouble(i); + } + return v; +} struct Encode { static ReturnedValue undefined() { @@ -519,21 +561,29 @@ private: Encode(void *); }; -inline -ReturnedValue Heap::Base::asReturnedValue() const +template<typename T> +ReturnedValue value_convert(ExecutionEngine *e, const Value &v); + +inline int Value::toInt32() const { - return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue(); -} + if (isInteger()) + return int_32; + double d = isNumber() ? doubleValue() : toNumberImpl(); + const double D32 = 4294967296.0; + const double D31 = D32 / 2.0; -template<typename T> -T *value_cast(const Value &v) + if ((d >= -D31 && d < D31)) + return static_cast<int>(d); + + return Primitive::toInt32(d); +} + +inline unsigned int Value::toUInt32() const { - return v.as<T>(); + return (unsigned int)toInt32(); } -template<typename T> -ReturnedValue value_convert(ExecutionEngine *e, const Value &v); } diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index 966f83acef..cd82159082 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -44,7 +44,7 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(VariantObject); Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value) - : Heap::Object(engine->emptyClass, engine->variantPrototype.asObject()) + : Heap::Object(engine->emptyClass, engine->variantPrototype()) { data = value; if (isScarce()) diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 2b48412c4d..b19f12bb98 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -49,7 +49,7 @@ #include <QtQml/qqmllist.h> #include <QtCore/qvariant.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4object_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index dda5848f0b..761e377f75 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -37,13 +37,14 @@ #include <QtCore/qjsondocument.h> #include <QtCore/qjsonobject.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4debugging_p.h> #include <private/qv4function_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4math_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qv4lookup_p.h> +#include <private/qv4string_p.h> #include <iostream> #include "qv4alloca_p.h" @@ -858,7 +859,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code engine->currentContext()->lineNumber = instr.lineNumber; if (qt_v4IsDebugging) qt_v4CheckForBreak(context, scopes, scopeDepth); - MOTH_END_INSTR(Debug) + MOTH_END_INSTR(Line) MOTH_BEGIN_INSTR(LoadThis) VALUE(instr.result) = context->thisObject(); diff --git a/src/qml/memory/memory.pri b/src/qml/memory/memory.pri new file mode 100644 index 0000000000..04b7566ccc --- /dev/null +++ b/src/qml/memory/memory.pri @@ -0,0 +1,14 @@ +INCLUDEPATH += $$PWD +INCLUDEPATH += $$OUT_PWD + +!qmldevtools_build { +SOURCES += \ + $$PWD/qv4mm.cpp \ + +HEADERS += \ + $$PWD/qv4mm_p.h + +} + +HEADERS += \ + $$PWD/qv4heap_p.h diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h new file mode 100644 index 0000000000..606fd47cbb --- /dev/null +++ b/src/qml/memory/qv4heap_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QV4HEAP_P_H +#define QV4HEAP_P_H + +#include <QtCore/QString> +#include <private/qv4global_p.h> + +QT_BEGIN_NAMESPACE + +namespace QV4 { + +struct VTable +{ + const VTable * const parent; + uint isExecutionContext : 1; + uint isString : 1; + uint isObject : 1; + uint isFunctionObject : 1; + uint isErrorObject : 1; + uint isArrayData : 1; + uint unused : 18; + uint type : 8; + const char *className; + void (*destroy)(Heap::Base *); + void (*markObjects)(Heap::Base *, ExecutionEngine *e); + bool (*isEqualTo)(Managed *m, Managed *other); +}; + +namespace Heap { + +struct Q_QML_EXPORT Base { + union { + const VTable *vtable; + quintptr mm_data; + }; + + inline ReturnedValue asReturnedValue() const; + inline void mark(QV4::ExecutionEngine *engine); + + enum { + MarkBit = 0x1, + NotInUse = 0x2, + PointerMask = ~0x3 + }; + + VTable *gcGetVtable() const { + return reinterpret_cast<VTable *>(mm_data & PointerMask); + } + inline bool isMarked() const { + return mm_data & MarkBit; + } + inline void setMarkBit() { + mm_data |= MarkBit; + } + inline void clearMarkBit() { + mm_data &= ~MarkBit; + } + + inline bool inUse() const { + return !(mm_data & NotInUse); + } + + Base *nextFree() { + return reinterpret_cast<Base *>(mm_data & PointerMask); + } + void setNextFree(Base *m) { + mm_data = (reinterpret_cast<quintptr>(m) | NotInUse); + } + + void *operator new(size_t, Managed *m) { return m; } + void *operator new(size_t, Heap::Base *m) { return m; } + void operator delete(void *, Heap::Base *) {} +}; + +template <typename T> +struct Pointer { + Pointer() {} + Pointer(T *t) : ptr(t) {} + + T *operator->() const { return ptr; } + operator T *() const { return ptr; } + + Pointer &operator =(T *t) { ptr = t; return *this; } + + template <typename Type> + Type *cast() { return static_cast<Type *>(ptr); } + + T *ptr; +}; + +} + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index d5576b400a..7dbf12ff11 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -381,7 +381,7 @@ void MemoryManager::sweep(bool lastSweep) { if (m_weakValues) { for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) { - if (Managed *m = (*it).asManaged()) { + if (Managed *m = (*it).as<Managed>()) { if (!m->markBit()) (*it) = Primitive::undefinedValue(); } @@ -525,7 +525,7 @@ void MemoryManager::runGC() size_t MemoryManager::getUsedMem() const { size_t usedMem = 0; - for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) { + for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) { Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base()); for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) { Heap::Base *m = reinterpret_cast<Heap::Base *>(item); @@ -607,7 +607,7 @@ void MemoryManager::collectFromJSStack() const Value *v = m_d->engine->jsStackBase; Value *top = m_d->engine->jsStackTop; while (v < top) { - Managed *m = v->asManaged(); + Managed *m = v->as<Managed>(); if (m && m->inUse()) // Skip pointers to already freed objects, they are bogus as well m->mark(m_d->engine); diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 00b41b796a..422809ba54 100644 --- a/src/qml/jsruntime/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -34,9 +34,9 @@ #ifndef QV4GC_H #define QV4GC_H -#include "qv4global_p.h" -#include "qv4value_inl_p.h" -#include "qv4scopedvalue_p.h" +#include <private/qv4global_p.h> +#include <private/qv4value_p.h> +#include <private/qv4scopedvalue_p.h> //#define DETAILED_MM_STATS diff --git a/src/qml/qml.pro b/src/qml/qml.pro index 6e06fb42ef..d75262bf0b 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -8,6 +8,9 @@ win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS win32:!wince*:!winrt:LIBS += -lshell32 solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 +# Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT. +gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks + MODULE_PLUGIN_TYPES = \ qmltooling @@ -33,6 +36,7 @@ HEADERS += qtqmlglobal.h \ #modules include(util/util.pri) +include(memory/memory.pri) include(parser/parser.pri) include(compiler/compiler.pri) include(jsapi/jsapi.pri) diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index e733bcec05..10ae9f0e52 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -35,7 +35,6 @@ SOURCES += \ $$PWD/qqmlimport.cpp \ $$PWD/qqmllist.cpp \ $$PWD/qqmllocale.cpp \ - $$PWD/qqmlabstractexpression.cpp \ $$PWD/qqmljavascriptexpression.cpp \ $$PWD/qqmlabstractbinding.cpp \ $$PWD/qqmlvaluetypeproxybinding.cpp \ @@ -107,7 +106,6 @@ HEADERS += \ $$PWD/qqmlscriptstring_p.h \ $$PWD/qqmllocale_p.h \ $$PWD/qqmlcomponentattached_p.h \ - $$PWD/qqmlabstractexpression_p.h \ $$PWD/qqmljavascriptexpression_p.h \ $$PWD/qqmlabstractbinding_p.h \ $$PWD/qqmlvaluetypeproxybinding_p.h \ diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp index 40c8f451b4..04fbb16764 100644 --- a/src/qml/qml/qqmlabstractbinding.cpp +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -39,14 +39,6 @@ QT_BEGIN_NAMESPACE -extern QQmlAbstractBinding::VTable QQmlBinding_vtable; -extern QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable; - -QQmlAbstractBinding::VTable *QQmlAbstractBinding::vTables[] = { - &QQmlBinding_vtable, - &QQmlValueTypeProxyBinding_vtable -}; - QQmlAbstractBinding::QQmlAbstractBinding(BindingType bt) : m_nextBindingPtr(bt) { @@ -72,20 +64,20 @@ void QQmlAbstractBinding::addToObject() Q_ASSERT(!nextBinding()); Q_ASSERT(isAddedToObject() == false); - QObject *obj = object(); + QObject *obj = targetObject(); Q_ASSERT(obj); QQmlData *data = QQmlData::get(obj, true); int coreIndex; - if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) { + if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) { // Value type // Find the value type proxy (if there is one) QQmlValueTypeProxyBinding *proxy = 0; if (data->hasBindingBit(coreIndex)) { QQmlAbstractBinding *b = data->bindings; - while (b && b->propertyIndex() != coreIndex) + while (b && b->targetPropertyIndex() != coreIndex) b = b->nextBinding(); Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy); proxy = static_cast<QQmlValueTypeProxyBinding *>(b); @@ -94,8 +86,8 @@ void QQmlAbstractBinding::addToObject() if (!proxy) { proxy = new QQmlValueTypeProxyBinding(obj, coreIndex); - Q_ASSERT(proxy->propertyIndex() == coreIndex); - Q_ASSERT(proxy->object() == obj); + Q_ASSERT(proxy->targetPropertyIndex() == coreIndex); + Q_ASSERT(proxy->targetObject() == obj); proxy->addToObject(); } @@ -118,59 +110,60 @@ Remove the binding from the object. */ void QQmlAbstractBinding::removeFromObject() { - if (isAddedToObject()) { - QObject *obj = object(); - QQmlData *data = QQmlData::get(obj, false); - Q_ASSERT(data); - - int coreIndex; - if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) { - - // Find the value type binding - QQmlAbstractBinding *vtbinding = data->bindings; - while (vtbinding->propertyIndex() != coreIndex) { - vtbinding = vtbinding->nextBinding(); - Q_ASSERT(vtbinding); - } - Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy); - - QQmlValueTypeProxyBinding *vtproxybinding = - static_cast<QQmlValueTypeProxyBinding *>(vtbinding); - - QQmlAbstractBinding *binding = vtproxybinding->m_bindings; - if (binding == this) { - vtproxybinding->m_bindings = nextBinding(); - } else { - while (binding->nextBinding() != this) { - binding = binding->nextBinding(); - Q_ASSERT(binding); - } - binding->setNextBinding(nextBinding()); - } + if (!isAddedToObject()) + return; + + QObject *obj = targetObject(); + QQmlData *data = QQmlData::get(obj, false); + Q_ASSERT(data); - // Value type - we don't remove the proxy from the object. It will sit their happily - // doing nothing until it is removed by a write, a binding change or it is reused - // to hold more sub-bindings. + int coreIndex; + if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) { + + // Find the value type binding + QQmlAbstractBinding *vtbinding = data->bindings; + while (vtbinding->targetPropertyIndex() != coreIndex) { + vtbinding = vtbinding->nextBinding(); + Q_ASSERT(vtbinding); + } + Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy); + QQmlValueTypeProxyBinding *vtproxybinding = + static_cast<QQmlValueTypeProxyBinding *>(vtbinding); + + QQmlAbstractBinding *binding = vtproxybinding->m_bindings; + if (binding == this) { + vtproxybinding->m_bindings = nextBinding(); } else { + while (binding->nextBinding() != this) { + binding = binding->nextBinding(); + Q_ASSERT(binding); + } + binding->setNextBinding(nextBinding()); + } - if (data->bindings == this) { - data->bindings = nextBinding(); - } else { - QQmlAbstractBinding *binding = data->bindings; - while (binding->nextBinding() != this) { - binding = binding->nextBinding(); - Q_ASSERT(binding); - } - binding->setNextBinding(nextBinding()); - } + // Value type - we don't remove the proxy from the object. It will sit their happily + // doing nothing until it is removed by a write, a binding change or it is reused + // to hold more sub-bindings. + + } else { - data->clearBindingBit(coreIndex); + if (data->bindings == this) { + data->bindings = nextBinding(); + } else { + QQmlAbstractBinding *binding = data->bindings; + while (binding->nextBinding() != this) { + binding = binding->nextBinding(); + Q_ASSERT(binding); + } + binding->setNextBinding(nextBinding()); } - setNextBinding(0); - setAddedToObject(false); + data->clearBindingBit(coreIndex); } + + setNextBinding(0); + setAddedToObject(false); } void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop) @@ -199,12 +192,7 @@ void QQmlAbstractBinding::clear() } } -void QQmlAbstractBinding::default_retargetBinding(QQmlAbstractBinding *, QObject *, int) -{ - qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding."); -} - -QString QQmlAbstractBinding::default_expression(const QQmlAbstractBinding *) +QString QQmlAbstractBinding::expression() const { return QLatin1String("<Unknown>"); } diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h index b5d8181ca5..d4cb4e0e9e 100644 --- a/src/qml/qml/qqmlabstractbinding_p.h +++ b/src/qml/qml/qqmlabstractbinding_p.h @@ -57,60 +57,29 @@ class QQmlObjectCreator; class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding { public: - enum DestroyMode { - - // The binding should disconnect itself upon destroy - DisconnectBinding, - - // The binding doesn't need to disconnect itself, but it can if it wants to. - // - // This is used in QQmlData::destroyed() - at the point at which the bindings are - // destroyed, the notifiers are already disconnected, so no need to disconnect each - // binding again. - // - // Bindings can use this flag to speed up destruction, especially for v4 bindings - // disconnecting a single binding might be slow. - KeepBindingConnected - }; - - struct VTable { - void (*destroy)(QQmlAbstractBinding *, DestroyMode destroyMode); - QString (*expression)(const QQmlAbstractBinding *); - int (*propertyIndex)(const QQmlAbstractBinding *); - QObject *(*object)(const QQmlAbstractBinding *); - void (*setEnabled)(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags); - void (*update)(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); - void (*retargetBinding)(QQmlAbstractBinding *, QObject *, int); - }; - typedef QWeakPointer<QQmlAbstractBinding> Pointer; enum BindingType { Binding = 0, ValueTypeProxy = 1 }; inline BindingType bindingType() const; - // Destroy the binding. Use this instead of calling delete. - // Bindings are free to implement their own memory management, so the delete operator is - // not necessarily safe. The default implementation clears the binding, removes it from - // the object and calls delete. - void destroy(DestroyMode destroyMode = DisconnectBinding) - { vtable()->destroy(this, destroyMode); } + void destroy() { + removeFromObject(); + clear(); + delete this; + } - QString expression() const { return vtable()->expression(this); } + virtual QString expression() const; // Should return the encoded property index for the binding. Should return this value // even if the binding is not enabled or added to an object. // Encoding is: coreIndex | (valueTypeIndex << 16) - int propertyIndex() const { return vtable()->propertyIndex(this); } + virtual int targetPropertyIndex() const = 0; // Should return the object for the binding. Should return this object even if the // binding is not enabled or added to the object. - QObject *object() const { return vtable()->object(this); } - - void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); } - void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f) { vtable()->setEnabled(this, e, f); } + virtual QObject *targetObject() const = 0; - void update() { update(QQmlPropertyPrivate::DontRemoveBinding); } - void update(QQmlPropertyPrivate::WriteFlags f) { vtable()->update(this, f); } + virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0; void addToObject(); void removeFromObject(); @@ -118,33 +87,20 @@ public: static inline Pointer getPointer(QQmlAbstractBinding *p); static void printBindingLoopError(QQmlProperty &prop); - // Default implementation for some VTable functions - template<typename T> - static void default_destroy(QQmlAbstractBinding *, DestroyMode); - static QString default_expression(const QQmlAbstractBinding *); - static void default_retargetBinding(QQmlAbstractBinding *, QObject *, int); + inline QQmlAbstractBinding *nextBinding() const; protected: QQmlAbstractBinding(BindingType); - ~QQmlAbstractBinding(); + virtual ~QQmlAbstractBinding(); void clear(); - // Called by QQmlPropertyPrivate to "move" a binding to a different property. - // This is only used for alias properties. The default implementation qFatal()'s - // to ensure that the method is never called for binding types that don't support it. - void retargetBinding(QObject *o, int i) { vtable()->retargetBinding(this, o, i); } - private: - Pointer weakPointer(); - friend class QQmlData; - friend class QQmlComponentPrivate; friend class QQmlValueTypeProxyBinding; - friend class QQmlPropertyPrivate; - friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>; - friend class QV4Bindings; friend class QQmlObjectCreator; + Pointer weakPointer(); + typedef QSharedPointer<QQmlAbstractBinding> SharedPointer; // To save memory, we also store the rarely used weakPointer() instance in here // We also use the flag bits: @@ -154,7 +110,6 @@ private: inline void setAddedToObject(bool v); inline bool isAddedToObject() const; - inline QQmlAbstractBinding *nextBinding() const; inline void setNextBinding(QQmlAbstractBinding *); // Pointer to the next binding in the linked list of bindings. @@ -166,9 +121,6 @@ private: // This saves a compiler-generated pointer to a compiler-generated vTable, and thus reduces // the binding object size by sizeof(void*). qintptr m_nextBindingPtr; - - static VTable *vTables[]; - inline const VTable *vtable() const { return vTables[bindingType()]; } }; QQmlAbstractBinding::Pointer @@ -202,18 +154,6 @@ QQmlAbstractBinding::BindingType QQmlAbstractBinding::bindingType() const return (BindingType)(m_nextBindingPtr & 0x3); } -template<typename T> -void QQmlAbstractBinding::default_destroy(QQmlAbstractBinding *This, DestroyMode mode) -{ - // Assume the binding disconnects itself in the destructor, which for example QQmlBinding - // does in the destructor of its base class, QQmlJavaScriptExpression - Q_UNUSED(mode); - - This->removeFromObject(); - This->clear(); - delete static_cast<T *>(This); -} - QT_END_NAMESPACE #endif // QQMLABSTRACTBINDING_P_H diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h deleted file mode 100644 index 82ba010434..0000000000 --- a/src/qml/qml/qqmlabstractexpression_p.h +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLABSTRACTEXPRESSION_P_H -#define QQMLABSTRACTEXPRESSION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qqmlcontext_p.h> -#include <private/qfieldlist_p.h> -#include <private/qflagpointer_p.h> - -QT_BEGIN_NAMESPACE - -class Q_QML_PRIVATE_EXPORT QQmlAbstractExpression -{ -public: - QQmlAbstractExpression(); - virtual ~QQmlAbstractExpression(); - - bool isValid() const; - - QQmlContextData *context() const; - void setContext(QQmlContextData *); - - virtual void refresh(); - - class DeleteWatcher { - public: - inline DeleteWatcher(QQmlAbstractExpression *); - inline ~DeleteWatcher(); - inline bool wasDeleted() const; - private: - friend class QQmlAbstractExpression; - QQmlContextData *_c; - QQmlAbstractExpression **_w; - QQmlAbstractExpression *_s; - }; - -private: - friend class QQmlContext; - friend class QQmlContextData; - friend class QQmlContextPrivate; - - QBiPointer<QQmlContextData, DeleteWatcher> m_context; - QQmlAbstractExpression **m_prevExpression; - QQmlAbstractExpression *m_nextExpression; -}; - -QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e) -: _c(0), _w(0), _s(e) -{ - if (e->m_context.isT1()) { - _w = &_s; - _c = e->m_context.asT1(); - e->m_context = this; - } else { - // Another watcher is already registered - _w = &e->m_context.asT2()->_s; - } -} - -QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher() -{ - Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2())); - if (*_w && _s->m_context.asT2() == this) - _s->m_context = _c; -} - -bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const -{ - return *_w == 0; -} - -QT_END_NAMESPACE - -#endif // QQMLABSTRACTEXPRESSION_P_H diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index f223d099e4..b9ca15af27 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -43,43 +43,30 @@ #include <private/qqmlscriptstring_p.h> #include <private/qqmlcontextwrapper_p.h> #include <private/qqmlbuiltinfunctions_p.h> +#include <private/qqmlvmemetaobject_p.h> #include <QVariant> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE -// Used in qqmlabstractbinding.cpp -QQmlAbstractBinding::VTable QQmlBinding_vtable = { - QQmlAbstractBinding::default_destroy<QQmlBinding>, - QQmlBinding::expression, - QQmlBinding::propertyIndex, - QQmlBinding::object, - QQmlBinding::setEnabled, - QQmlBinding::update, - QQmlBinding::retargetBinding -}; - QQmlBinding::Identifier QQmlBinding::Invalid = -1; -static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = { - QQmlBinding::expressionIdentifier, - QQmlBinding::expressionChanged -}; - QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt) -: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding) + : QQmlJavaScriptExpression(), + QQmlAbstractBinding(Binding) { setNotifyOnValueChanged(true); - QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt)); + QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt)); setScopeObject(obj); QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine(); - v4function.set(v4, qmlBinding(context(), obj, str, QString(), 0)); + m_function.set(v4, qmlBinding(context(), obj, str, QString(), 0)); } QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt) -: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding) + : QQmlJavaScriptExpression(), + QQmlAbstractBinding(Binding) { if (ctxt && !ctxt->isValid()) return; @@ -100,51 +87,54 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte } setNotifyOnValueChanged(true); - QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context)); + QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context)); setScopeObject(obj ? obj : scriptPrivate->scope); QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine(); if (runtimeFunction) { - v4function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction)); + m_function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction)); } else { QString code = scriptPrivate->script; - v4function.set(v4, qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber)); + m_function.set(v4, qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber)); } } QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt) -: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding) + : QQmlJavaScriptExpression(), + QQmlAbstractBinding(Binding) { setNotifyOnValueChanged(true); - QQmlAbstractExpression::setContext(ctxt); + QQmlJavaScriptExpression::setContext(ctxt); setScopeObject(obj); QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine(); - v4function.set(v4, qmlBinding(ctxt, obj, str, QString(), 0)); + m_function.set(v4, qmlBinding(ctxt, obj, str, QString(), 0)); } QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt, const QString &url, quint16 lineNumber, quint16 columnNumber) -: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding) + : QQmlJavaScriptExpression(), + QQmlAbstractBinding(Binding) { Q_UNUSED(columnNumber); setNotifyOnValueChanged(true); - QQmlAbstractExpression::setContext(ctxt); + QQmlJavaScriptExpression::setContext(ctxt); setScopeObject(obj); QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine(); - v4function.set(v4, qmlBinding(ctxt, obj, str, url, lineNumber)); + m_function.set(v4, qmlBinding(ctxt, obj, str, url, lineNumber)); } QQmlBinding::QQmlBinding(const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt) -: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding) + : QQmlJavaScriptExpression(), + QQmlAbstractBinding(Binding) { setNotifyOnValueChanged(true); - QQmlAbstractExpression::setContext(ctxt); + QQmlJavaScriptExpression::setContext(ctxt); setScopeObject(obj); - v4function.set(functionPtr.asObject()->engine(), functionPtr); + m_function.set(functionPtr.as<QV4::Object>()->engine(), functionPtr); } QQmlBinding::~QQmlBinding() @@ -162,90 +152,88 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) return; // Check that the target has not been deleted - if (QQmlData::wasDeleted(object())) + if (QQmlData::wasDeleted(targetObject())) return; QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); QV4::Scope scope(ep->v4engine()); - QV4::ScopedFunctionObject f(scope, v4function.value()); + QV4::ScopedFunctionObject f(scope, m_function.value()); Q_ASSERT(f); - if (!updatingFlag()) { - QQmlBindingProfiler prof(ep->profiler, f); - setUpdatingFlag(true); + if (updatingFlag()) { + QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), m_core, 0); + QQmlAbstractBinding::printBindingLoopError(p); + return; + } - QQmlAbstractExpression::DeleteWatcher watcher(this); + QQmlBindingProfiler prof(ep->profiler, f); + setUpdatingFlag(true); - if (m_core.propType == qMetaTypeId<QQmlBinding *>()) { + QQmlJavaScriptExpression::DeleteWatcher watcher(this); - int idx = m_core.coreIndex; - Q_ASSERT(idx != -1); + if (m_core.propType == qMetaTypeId<QQmlBinding *>()) { - QQmlBinding *t = this; - int status = -1; - void *a[] = { &t, 0, &status, &flags }; - QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a); + int idx = m_core.coreIndex; + Q_ASSERT(idx != -1); - } else { - ep->referenceScarceResources(); + QQmlBinding *t = this; + int status = -1; + void *a[] = { &t, 0, &status, &flags }; + QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a); - bool isUndefined = false; + } else { + ep->referenceScarceResources(); - QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined)); + bool isUndefined = false; - bool needsErrorLocationData = false; - if (!watcher.wasDeleted() && !hasError()) - needsErrorLocationData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(), - this, result, isUndefined, flags); + QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined)); - if (!watcher.wasDeleted()) { + bool needsErrorLocationData = false; + if (!watcher.wasDeleted() && !hasError()) + needsErrorLocationData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(), + this, result, isUndefined, flags); - if (needsErrorLocationData) - delayedError()->setErrorLocation(f->sourceLocation()); + if (!watcher.wasDeleted()) { - if (hasError()) { - if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine)); - } else { - clearError(); - } + if (needsErrorLocationData) + delayedError()->setErrorLocation(f->sourceLocation()); + if (hasError()) { + if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine)); + } else { + clearError(); } - ep->dereferenceScarceResources(); } - if (!watcher.wasDeleted()) - setUpdatingFlag(false); - } else { - QQmlProperty p = property(); - QQmlAbstractBinding::printBindingLoopError(p); + ep->dereferenceScarceResources(); } + + if (!watcher.wasDeleted()) + setUpdatingFlag(false); } QVariant QQmlBinding::evaluate() { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); - QV4::Scope scope(ep->v4engine()); ep->referenceScarceResources(); bool isUndefined = false; - QV4::ScopedValue f(scope, v4function.value()); - QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined)); + QV4::Scope scope(ep->v4engine()); + QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined)); ep->dereferenceScarceResources(); return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >()); } -QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e) +QString QQmlBinding::expressionIdentifier() { - QQmlBinding *This = static_cast<QQmlBinding *>(e); - - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(This->context()->engine); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); QV4::Scope scope(ep->v4engine()); - QV4::ScopedValue f(scope, This->v4function.value()); - QV4::Function *function = f->asFunctionObject()->function(); + QV4::ScopedValue f(scope, m_function.value()); + QV4::Function *function = f->as<QV4::FunctionObject>()->function(); QString url = function->sourceFile(); quint16 lineNumber = function->compiledFunction->location.line; @@ -254,10 +242,9 @@ QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e) return url + QLatin1Char(':') + QString::number(lineNumber) + QLatin1Char(':') + QString::number(columnNumber); } -void QQmlBinding::expressionChanged(QQmlJavaScriptExpression *e) +void QQmlBinding::expressionChanged() { - QQmlBinding *This = static_cast<QQmlBinding *>(e); - This->update(); + update(); } void QQmlBinding::refresh() @@ -265,36 +252,6 @@ void QQmlBinding::refresh() update(); } -QString QQmlBinding::expression(const QQmlAbstractBinding *This) -{ - return static_cast<const QQmlBinding *>(This)->expression(); -} - -int QQmlBinding::propertyIndex(const QQmlAbstractBinding *This) -{ - return static_cast<const QQmlBinding *>(This)->propertyIndex(); -} - -QObject *QQmlBinding::object(const QQmlAbstractBinding *This) -{ - return static_cast<const QQmlBinding *>(This)->object(); -} - -void QQmlBinding::setEnabled(QQmlAbstractBinding *This, bool e, QQmlPropertyPrivate::WriteFlags f) -{ - static_cast<QQmlBinding *>(This)->setEnabled(e, f); -} - -void QQmlBinding::update(QQmlAbstractBinding *This , QQmlPropertyPrivate::WriteFlags f) -{ - static_cast<QQmlBinding *>(This)->update(f); -} - -void QQmlBinding::retargetBinding(QQmlAbstractBinding *This, QObject *o, int i) -{ - static_cast<QQmlBinding *>(This)->retargetBinding(o, i); -} - void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) { setEnabledFlag(e); @@ -307,44 +264,65 @@ void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) QString QQmlBinding::expression() const { QV4::Scope scope(QQmlEnginePrivate::get(context()->engine)->v4engine()); - QV4::ScopedValue v(scope, v4function.value()); + QV4::ScopedValue v(scope, m_function.value()); return v->toQStringNoThrow(); } -QObject *QQmlBinding::object() const +QObject *QQmlBinding::targetObject() const { - if (m_coreObject.hasValue()) return m_coreObject.constValue()->target; - else return *m_coreObject; + return *m_coreObject; } -int QQmlBinding::propertyIndex() const +int QQmlBinding::targetPropertyIndex() const { - if (m_coreObject.hasValue()) return m_coreObject.constValue()->targetProperty; - else return m_core.encodedIndex(); -} - -void QQmlBinding::retargetBinding(QObject *t, int i) -{ - m_coreObject.value().target = t; - m_coreObject.value().targetProperty = i; + return m_core.encodedIndex(); } void QQmlBinding::setTarget(const QQmlProperty &prop) { - setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core, - QQmlPropertyPrivate::get(prop)->context); + setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core); } -void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, QQmlContextData *ctxt) +void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core) { m_coreObject = object; m_core = core; - m_ctxt = ctxt; -} -QQmlProperty QQmlBinding::property() const -{ - return QQmlPropertyPrivate::restore(object(), m_core, *m_ctxt); + while (m_core.isAlias()) { + int coreIndex = core.coreIndex; + int valueTypeIndex = core.getValueTypeCoreIndex(); + QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex); + + int aValueTypeIndex; + if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) { + m_core.coreIndex = -1; + m_coreObject = 0; + return; + } + if (valueTypeIndex == -1) + valueTypeIndex = aValueTypeIndex; + + QQmlData *data = QQmlData::get(object, false); + if (!data || !data->propertyCache) { + m_core.coreIndex = -1; + m_coreObject = 0; + return; + } + QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex); + Q_ASSERT(propertyData); + + m_coreObject = object; + m_core = *propertyData; + if (valueTypeIndex != -1) { + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(m_core.propType); + Q_ASSERT(valueTypeMetaObject); + QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex); + m_core.setFlags(m_core.getFlags() | QQmlPropertyData::IsValueTypeVirtual); + m_core.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp); + m_core.valueTypePropType = vtProp.userType(); + m_core.valueTypeCoreIndex = valueTypeIndex; + } + } } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 1e440b2e86..99c1699168 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -57,14 +57,12 @@ #include <private/qpointervaluepair_p.h> #include <private/qqmlabstractbinding_p.h> -#include <private/qqmlabstractexpression_p.h> #include <private/qqmljavascriptexpression_p.h> QT_BEGIN_NAMESPACE class QQmlContext; class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlJavaScriptExpression, - public QQmlAbstractExpression, public QQmlAbstractBinding { public: @@ -76,82 +74,60 @@ public: QQmlBinding(const QV4::Value &, QObject *, QQmlContextData *); void setTarget(const QQmlProperty &); - void setTarget(QObject *, const QQmlPropertyData &, QQmlContextData *); - QQmlProperty property() const; + void setTarget(QObject *, const QQmlPropertyData &); void setNotifyOnValueChanged(bool); - // Inherited from QQmlAbstractExpression + // Inherited from QQmlJavaScriptExpression virtual void refresh(); - // "Inherited" from QQmlAbstractBinding - static QString expression(const QQmlAbstractBinding *); - static int propertyIndex(const QQmlAbstractBinding *); - static QObject *object(const QQmlAbstractBinding *); - static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags); - static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); - static void retargetBinding(QQmlAbstractBinding *, QObject *, int); - - void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags); - void update(QQmlPropertyPrivate::WriteFlags flags); - void update() { update(QQmlPropertyPrivate::DontRemoveBinding); } - - QString expression() const; - QObject *object() const; - int propertyIndex() const; - void retargetBinding(QObject *, int); + // Inherited from QQmlAbstractBinding + virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding); + virtual QString expression() const; + virtual QObject *targetObject() const; + virtual int targetPropertyIndex() const; + void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding); typedef int Identifier; static Identifier Invalid; QVariant evaluate(); - static QString expressionIdentifier(QQmlJavaScriptExpression *); - static void expressionChanged(QQmlJavaScriptExpression *); + virtual QString expressionIdentifier(); + virtual void expressionChanged(); protected: friend class QQmlAbstractBinding; ~QQmlBinding(); private: - QV4::PersistentValue v4function; - inline bool updatingFlag() const; inline void setUpdatingFlag(bool); inline bool enabledFlag() const; inline void setEnabledFlag(bool); - struct Retarget { - QObject *target; - int targetProperty; - }; - - QPointerValuePair<QObject, Retarget> m_coreObject; + QFlagPointer<QObject> m_coreObject; QQmlPropertyData m_core; - // We store some flag bits in the following flag pointers. - // m_ctxt:flag1 - updatingFlag - // m_ctxt:flag2 - enabledFlag - QFlagPointer<QQmlContextData> m_ctxt; }; bool QQmlBinding::updatingFlag() const { - return m_ctxt.flag(); + return m_coreObject.flag(); } void QQmlBinding::setUpdatingFlag(bool v) { - m_ctxt.setFlagValue(v); + m_coreObject.setFlagValue(v); } bool QQmlBinding::enabledFlag() const { - return m_ctxt.flag2(); + return m_coreObject.flag2(); } void QQmlBinding::setEnabledFlag(bool v) { - m_ctxt.setFlag2Value(v); + m_coreObject.setFlag2Value(v); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 766e657c59..77dccf6f04 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -47,7 +47,7 @@ #include <private/qqmlcompiler_p.h> #include "qqmlinfo.h" -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <QtCore/qstringbuilder.h> #include <QtCore/qdebug.h> @@ -55,11 +55,6 @@ QT_BEGIN_NAMESPACE -static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = { - QQmlBoundSignalExpression::expressionIdentifier, - QQmlBoundSignalExpression::expressionChanged -}; - QQmlBoundSignalExpression::ExtraData::ExtraData(const QString &handlerName, const QString ¶meterString, const QString &expression, const QString &fileName, quint16 line, quint16 column) @@ -75,7 +70,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, const QString &fileName, quint16 line, quint16 column, const QString &handlerName, const QString ¶meterString) - : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable), + : QQmlJavaScriptExpression(), m_index(index), m_target(target), m_extra(new ExtraData(handlerName, parameterString, expression, fileName, line, column)) @@ -87,12 +82,13 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, } QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::Value &function) - : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable), + : QQmlJavaScriptExpression(), m_index(index), - m_function(function.asObject()->engine(), function), m_target(target), m_extra(0) { + m_function.set(function.as<QV4::Object>()->engine(), function); + setExpressionFunctionValid(true); setInvalidParameterName(false); @@ -100,7 +96,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, } QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction) - : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable), + : QQmlJavaScriptExpression(), m_index(index), m_target(target), m_extra(0) @@ -137,14 +133,13 @@ QQmlBoundSignalExpression::~QQmlBoundSignalExpression() delete m_extra.data(); } -QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e) +QString QQmlBoundSignalExpression::expressionIdentifier() { - QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e); - QQmlSourceLocation loc = This->sourceLocation(); + QQmlSourceLocation loc = sourceLocation(); return loc.sourceFile + QLatin1Char(':') + QString::number(loc.line); } -void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *) +void QQmlBoundSignalExpression::expressionChanged() { // bound signals do not notify on change. } @@ -254,7 +249,6 @@ void QQmlBoundSignalExpression::evaluate(void **a) int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0); int argCount = argsTypes ? *argsTypes : 0; - QV4::ScopedValue f(scope, m_function.value()); QV4::ScopedCallData callData(scope, argCount); for (int ii = 0; ii < argCount; ++ii) { int type = argsTypes[ii + 1]; @@ -278,7 +272,7 @@ void QQmlBoundSignalExpression::evaluate(void **a) } } - QQmlJavaScriptExpression::evaluate(context(), f, callData, 0); + QQmlJavaScriptExpression::evaluate(callData, 0); } ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index 8d677ea039..bc30b25d6a 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -47,7 +47,6 @@ #include <QtCore/qmetaobject.h> -#include <private/qqmlabstractexpression_p.h> #include <private/qqmljavascriptexpression_p.h> #include <private/qqmlboundsignalexpressionpointer_p.h> #include <private/qqmlnotifier_p.h> @@ -58,7 +57,7 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpression, public QQmlJavaScriptExpression, public QQmlRefCount +class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlJavaScriptExpression, public QQmlRefCount { public: QQmlBoundSignalExpression(QObject *target, int index, @@ -73,9 +72,9 @@ public: QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction); - // "inherited" from QQmlJavaScriptExpression. - static QString expressionIdentifier(QQmlJavaScriptExpression *); - static void expressionChanged(QQmlJavaScriptExpression *); + // inherited from QQmlJavaScriptExpression. + virtual QString expressionIdentifier(); + virtual void expressionChanged(); // evaluation of a bound signal expression doesn't return any value void evaluate(void **a); @@ -99,8 +98,6 @@ private: void setInvalidParameterName(bool v) { m_extra.setFlag2Value(v); } int m_index; - QV4::PersistentValue m_function; - QObject *m_target; // only needed when !expressionFunctionValid() diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index a36b742085..8795d6d07a 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1216,7 +1216,7 @@ void QQmlComponent::createObject(QQmlV4Function *args) if (args->length() >= 2) { QV4::ScopedValue v(scope, (*args)[1]); - if (!v->asObject() || v->asArrayObject()) { + if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) { qmlInfo(this) << tr("createObject: value is not an object"); args->setReturnValue(QV4::Encode::null()); return; @@ -1242,12 +1242,12 @@ void QQmlComponent::createObject(QQmlV4Function *args) if (!valuemap->isUndefined()) { QV4::ScopedObject qmlglobal(scope, args->qmlGlobal()); QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal)); - Q_ASSERT(f->asFunctionObject()); + Q_ASSERT(f->as<QV4::FunctionObject>()); QV4::ScopedCallData callData(scope, 2); - callData->thisObject = v4->globalObject(); + callData->thisObject = v4->globalObject; callData->args[0] = object; callData->args[1] = valuemap; - f->asFunctionObject()->call(callData); + f->as<QV4::FunctionObject>()->call(callData); } d->completeCreate(); @@ -1342,7 +1342,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) if (args->length() >= 2) { QV4::ScopedValue v(scope, (*args)[1]); if (v->isNull()) { - } else if (!v->asObject() || v->asArrayObject()) { + } else if (!v->as<QV4::Object>() || v->as<QV4::ArrayObject>()) { qmlInfo(this) << tr("createObject: value is not an object"); args->setReturnValue(QV4::Encode::null()); return; @@ -1390,14 +1390,14 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu QV4::Scope scope(v4engine); QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate)); - Q_ASSERT(object->asObject()); + Q_ASSERT(object->as<QV4::Object>()); if (!valuemap.isUndefined()) { QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal); QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj)); QV4::ScopedCallData callData(scope, 2); - callData->thisObject = v4engine->globalObject(); + callData->thisObject = v4engine->globalObject; callData->args[0] = object; callData->args[1] = valuemap; f->call(callData); @@ -1492,9 +1492,9 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o) QV4::ExecutionEngine *v4 = engine(); QV4::Scope scope(v4); - QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject())); + QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.as<Object>())); QV4::ScopedCallData callData(scope, 2); - callData->thisObject = v4->globalObject(); + callData->thisObject = v4->globalObject; callData->args[0] = QV4::QObjectWrapper::wrap(v4, o); callData->args[1] = d()->valuemap; f->call(callData); diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index f08f650913..052f371516 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -585,9 +585,9 @@ void QQmlContextData::clearContext() { emitDestruction(); - QQmlAbstractExpression *expression = expressions; + QQmlJavaScriptExpression *expression = expressions; while (expression) { - QQmlAbstractExpression *nextExpression = expression->m_nextExpression; + QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression; expression->m_prevExpression = 0; expression->m_nextExpression = 0; @@ -652,9 +652,9 @@ void QQmlContextData::setParent(QQmlContextData *p, bool parentTakesOwnership) } } -void QQmlContextData::refreshExpressionsRecursive(QQmlAbstractExpression *expression) +void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression) { - QQmlAbstractExpression::DeleteWatcher w(expression); + QQmlJavaScriptExpression::DeleteWatcher w(expression); if (expression->m_nextExpression) refreshExpressionsRecursive(expression->m_nextExpression); @@ -808,7 +808,7 @@ 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(); + for (QHash<int, int>::ConstIterator it = objectIndexToId.cbegin(), end = objectIndexToId.cend(); it != end; ++it) { const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key()); const QString name = typeCompilationUnit->data->stringAt(obj->idIndex); diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index f5fd7d0a5c..95254d4baa 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -69,7 +69,7 @@ class QQmlExpression; class QQmlEngine; class QQmlExpression; class QQmlExpressionPrivate; -class QQmlAbstractExpression; +class QQmlJavaScriptExpression; class QQmlContextData; class QQmlContextPrivate : public QObjectPrivate @@ -171,7 +171,7 @@ public: QQmlContextData **prevChild; // Expressions that use this context - QQmlAbstractExpression *expressions; + QQmlJavaScriptExpression *expressions; // Doubly-linked list of objects that are owned by this context QQmlData *contextObjects; @@ -212,7 +212,7 @@ public: private: void refreshExpressionsRecursive(bool isGlobal); - void refreshExpressionsRecursive(QQmlAbstractExpression *); + void refreshExpressionsRecursive(QQmlJavaScriptExpression *); ~QQmlContextData() {} }; diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 5844eab54f..9b921b9fad 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -38,7 +38,7 @@ #include <private/qqmlcontext_p.h> #include <private/qv4engine_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4objectproto_p.h> #include <private/qv4mm_p.h> #include <private/qv4function_p.h> @@ -106,7 +106,7 @@ QQmlContextData *QmlContextWrapper::getContext(const Value &value) if (!value.isObject()) return 0; - QV4::ExecutionEngine *v4 = value.asObject()->engine(); + QV4::ExecutionEngine *v4 = value.as<Object>()->engine(); Scope scope(v4); QV4::Scoped<QmlContextWrapper> c(scope, value); @@ -117,7 +117,7 @@ void QmlContextWrapper::takeContextOwnership(const Value &qmlglobal) { Q_ASSERT(qmlglobal.isObject()); - QV4::ExecutionEngine *v4 = qmlglobal.asObject()->engine(); + QV4::ExecutionEngine *v4 = qmlglobal.as<Object>()->engine(); Scope scope(v4); QV4::Scoped<QmlContextWrapper> c(scope, qmlglobal); Q_ASSERT(c); @@ -125,17 +125,17 @@ void QmlContextWrapper::takeContextOwnership(const Value &qmlglobal) } -ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QmlContextWrapper>()); - QmlContextWrapper *resource = static_cast<QmlContextWrapper *>(m); + const QmlContextWrapper *resource = static_cast<const QmlContextWrapper *>(m); QV4::ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); // In V8 the JS global object would come _before_ the QML global object, // so simulate that here. bool hasProp; - QV4::ScopedValue result(scope, v4->globalObject()->get(name, &hasProp)); + QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp)); if (hasProp) { if (hasProperty) *hasProperty = hasProp; @@ -431,10 +431,10 @@ Heap::QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QV4::QmlCo { } -ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue QQmlIdObjectsArray::getIndexed(const Managed *m, uint index, bool *hasProperty) { - Scope scope(static_cast<QV4::QQmlIdObjectsArray*>(m)->engine()); - Scoped<QQmlIdObjectsArray> This(scope, static_cast<QV4::QQmlIdObjectsArray*>(m)); + Scope scope(static_cast<const QV4::QQmlIdObjectsArray*>(m)->engine()); + Scoped<QQmlIdObjectsArray> This(scope, static_cast<const QV4::QQmlIdObjectsArray*>(m)); Scoped<QmlContextWrapper> contextWrapper(scope, This->d()->contextWrapper); QQmlContextData *context = contextWrapper->getContext(); if (!context) { diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index 52d8677103..c569d09cd7 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -48,7 +48,7 @@ #include <QtCore/qglobal.h> #include <private/qtqmlglobal_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4object_p.h> #include <private/qqmlcontext_p.h> #include <private/qv4functionobject_p.h> @@ -81,7 +81,7 @@ struct QmlContextWrapper : Object { struct QQmlIdObjectsArray : Object { QQmlIdObjectsArray(QV4::ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper); - QmlContextWrapper *contextWrapper; + Pointer<QmlContextWrapper> contextWrapper; }; } @@ -103,7 +103,7 @@ struct Q_QML_EXPORT QmlContextWrapper : Object void setReadOnly(bool b) { d()->readOnly = b; } - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); static void markObjects(Heap::Base *m, ExecutionEngine *engine); @@ -118,7 +118,7 @@ struct QQmlIdObjectsArray : public Object { V4_OBJECT2(QQmlIdObjectsArray, Object) - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); static void markObjects(Heap::Base *that, ExecutionEngine *engine); }; diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 04c42b638d..5cef128e7e 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -48,8 +48,9 @@ #include <private/qtqmlglobal_p.h> #include <private/qobject_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4persistent_p.h> +#include <qjsengine.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 8a7e4b84e7..fc5d672372 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -247,6 +247,10 @@ void QQmlEnginePrivate::activateDesignerMode() The QQuickImageProvider::requestPixmap() method will be called for all image requests. \value Texture The Image Provider provides QSGTextureProvider based images. The QQuickImageProvider::requestTexture() method will be called for all image requests. + \value ImageResponse The Image provider provides QQuickTextureFactory based images. + Should only be used in QQuickAsyncImageProvider or its subclasses. + The QQuickAsyncImageProvider::requestImageResponse() method will be called for all image requests. + Since Qt 5.6 \omitvalue Invalid */ @@ -595,8 +599,8 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e) QQmlEnginePrivate::~QQmlEnginePrivate() { - typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator TypePropertyCacheIt; - typedef QHash<int, QQmlCompiledData *>::Iterator CompositeTypesIt; + typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt; + typedef QHash<int, QQmlCompiledData *>::const_iterator CompositeTypesIt; if (inProgressCreations) qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations); @@ -615,9 +619,9 @@ QQmlEnginePrivate::~QQmlEnginePrivate() if (incubationController) incubationController->d = 0; incubationController = 0; - for (TypePropertyCacheIt iter = typePropertyCache.begin(), end = typePropertyCache.end(); iter != end; ++iter) + for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter) (*iter)->release(); - for (CompositeTypesIt iter = m_compositeTypes.begin(), end = m_compositeTypes.end(); iter != end; ++iter) { + for (CompositeTypesIt iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) { iter.value()->isRegisteredWithEngine = false; // since unregisterInternalCompositeType() will not be called in this @@ -812,10 +816,10 @@ void QQmlData::flushPendingBindingImpl(int coreIndex) // Find the binding QQmlAbstractBinding *b = bindings; - while (b && *b->m_mePtr && b->propertyIndex() != coreIndex) + while (b && *b->m_mePtr && b->targetPropertyIndex() != coreIndex) b = b->nextBinding(); - if (b && b->propertyIndex() == coreIndex) { + if (b && b->targetPropertyIndex() == coreIndex) { b->clear(); b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); @@ -2243,8 +2247,8 @@ bool QQmlEnginePrivate::isList(int t) const int QQmlEnginePrivate::listType(int t) const { Locker locker(this); - QHash<int, int>::ConstIterator iter = m_qmlLists.find(t); - if (iter != m_qmlLists.end()) + QHash<int, int>::ConstIterator iter = m_qmlLists.constFind(t); + if (iter != m_qmlLists.cend()) return *iter; else return QQmlMetaType::listType(t); @@ -2253,8 +2257,8 @@ int QQmlEnginePrivate::listType(int t) const QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const { Locker locker(this); - QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t); - if (iter != m_compositeTypes.end()) { + QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t); + if (iter != m_compositeTypes.cend()) { return QQmlMetaObject((*iter)->rootPropertyCache); } else { QQmlType *type = QQmlMetaType::qmlType(t); @@ -2265,8 +2269,8 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const { Locker locker(this); - QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t); - if (iter != m_compositeTypes.end()) { + QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t); + if (iter != m_compositeTypes.cend()) { return QQmlMetaObject((*iter)->rootPropertyCache); } else { QQmlType *type = QQmlMetaType::qmlType(t); @@ -2277,8 +2281,8 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t) { Locker locker(this); - QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t); - if (iter != m_compositeTypes.end()) { + QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t); + if (iter != m_compositeTypes.cend()) { return (*iter)->rootPropertyCache; } else { QQmlType *type = QQmlMetaType::qmlType(t); @@ -2290,8 +2294,8 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t) QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t) { Locker locker(this); - QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t); - if (iter != m_compositeTypes.end()) { + QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t); + if (iter != m_compositeTypes.cend()) { return (*iter)->rootPropertyCache; } else { QQmlType *type = QQmlMetaType::qmlType(t); diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index df673c1fd5..61a884279d 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -52,7 +52,9 @@ public: Image, Pixmap, Texture, - Invalid + Invalid, + ImageResponse + // ### Qt6: reorder these, and give Invalid a fixed large value }; enum Flag { diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 35e0bc8c64..3813281044 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -45,13 +45,8 @@ QT_BEGIN_NAMESPACE -static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = { - QQmlExpressionPrivate::expressionIdentifier, - QQmlExpressionPrivate::expressionChanged -}; - QQmlExpressionPrivate::QQmlExpressionPrivate() -: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable), +: QQmlJavaScriptExpression(), expressionFunctionValid(true), line(0), column(0) { @@ -65,7 +60,7 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb { expression = expr; - QQmlAbstractExpression::setContext(ctxt); + QQmlJavaScriptExpression::setContext(ctxt); setScopeObject(me); expressionFunctionValid = false; } @@ -74,9 +69,9 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFu { expressionFunctionValid = true; QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine); - function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction)); + m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction)); - QQmlAbstractExpression::setContext(ctxt); + QQmlJavaScriptExpression::setContext(ctxt); setScopeObject(me); } @@ -251,13 +246,11 @@ QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined) QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine(); if (!expressionFunctionValid) { - function.set(v4, qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope)); + m_function.set(v4, qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope)); expressionFunctionValid = true; } - QV4::Scope scope(v4); - QV4::ScopedValue f(scope, function.value()); - return evaluate(context(), f, isUndefined); + return evaluate(isUndefined); } QVariant QQmlExpressionPrivate::value(bool *isUndefined) @@ -432,22 +425,15 @@ QQmlError QQmlExpression::error() const calling QQmlExpression::evaluate()) before this signal will be emitted. */ -void QQmlExpressionPrivate::expressionChanged(QQmlJavaScriptExpression *e) -{ - QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e); - This->expressionChanged(); -} - void QQmlExpressionPrivate::expressionChanged() { Q_Q(QQmlExpression); emit q->valueChanged(); } -QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e) +QString QQmlExpressionPrivate::expressionIdentifier() { - QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e); - return QLatin1Char('"') + This->expression + QLatin1Char('"'); + return QLatin1Char('"') + expression + QLatin1Char('"'); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h index d8da387878..0419c9c11c 100644 --- a/src/qml/qml/qqmlexpression_p.h +++ b/src/qml/qml/qqmlexpression_p.h @@ -52,7 +52,6 @@ #include <private/qflagpointer_p.h> #include <private/qdeletewatcher_p.h> #include <private/qpointervaluepair_p.h> -#include <private/qqmlabstractexpression_p.h> #include <private/qqmljavascriptexpression_p.h> QT_BEGIN_NAMESPACE @@ -60,8 +59,7 @@ QT_BEGIN_NAMESPACE class QQmlExpression; class QString; class QQmlExpressionPrivate : public QObjectPrivate, - public QQmlJavaScriptExpression, - public QQmlAbstractExpression + public QQmlJavaScriptExpression { Q_DECLARE_PUBLIC(QQmlExpression) public: @@ -82,15 +80,13 @@ public: bool expressionFunctionValid:1; - // "Inherited" from QQmlJavaScriptExpression - static QString expressionIdentifier(QQmlJavaScriptExpression *); - static void expressionChanged(QQmlJavaScriptExpression *); + // Inherited from QQmlJavaScriptExpression + virtual QString expressionIdentifier(); virtual void expressionChanged(); QString expression; QV4::PersistentValue qmlscope; - QV4::PersistentValue function; QString url; // This is a QString for a reason. QUrls are slooooooow... quint16 line; diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 02bd1c4b83..cc57d855c3 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -35,7 +35,7 @@ #include <private/qqmlexpression_p.h> #include <private/qqmlcontextwrapper_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4script_p.h> #include <private/qv4errorobject_p.h> @@ -83,13 +83,22 @@ void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine) } -QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v) -: m_vtable(v) +QQmlJavaScriptExpression::QQmlJavaScriptExpression() + : m_error(0), + m_context(0), + m_prevExpression(0), + m_nextExpression(0) { } QQmlJavaScriptExpression::~QQmlJavaScriptExpression() { + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + } + clearGuards(); if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion. m_scopeObject.asT2()->_s = 0; @@ -106,40 +115,62 @@ void QQmlJavaScriptExpression::resetNotifyOnValueChanged() clearGuards(); } -QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context, - const QV4::Value &function, bool *isUndefined) +void QQmlJavaScriptExpression::setContext(QQmlContextData *context) { - QV4::ExecutionEngine *v4 = QV8Engine::getV4(context->engine); + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + m_prevExpression = 0; + m_nextExpression = 0; + } + + m_context = context; + + if (context) { + m_nextExpression = context->expressions; + if (m_nextExpression) + m_nextExpression->m_prevExpression = &m_nextExpression; + m_prevExpression = &context->expressions; + context->expressions = this; + } +} + +void QQmlJavaScriptExpression::refresh() +{ +} + +QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined) +{ + QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_context->engine); QV4::Scope scope(v4); QV4::ScopedCallData callData(scope); - return evaluate(context, function, callData, isUndefined); + return evaluate(callData, isUndefined); } -QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context, - const QV4::Value &function, - QV4::CallData *callData, - bool *isUndefined) +QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined) { - Q_ASSERT(context && context->engine); + Q_ASSERT(m_context && m_context->engine); - if (function.isUndefined()) { + QV4::Value *f = m_function.valueRef(); + if (!f || f->isUndefined()) { if (isUndefined) *isUndefined = true; return QV4::Encode::undefined(); } - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine); // All code that follows must check with watcher before it accesses data members // incase we have been deleted. DeleteWatcher watcher(this); Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty()); - GuardCapture capture(context->engine, this, &watcher); + GuardCapture capture(m_context->engine, this, &watcher); QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture; - ep->propertyCapture = notifyOnValueChanged()?&capture:0; + ep->propertyCapture = notifyOnValueChanged() ? &capture : 0; if (notifyOnValueChanged()) @@ -148,14 +179,14 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context, QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine()); QV4::Scope scope(v4); QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue()); - callData->thisObject = v4->globalObject(); + callData->thisObject = v4->globalObject; if (scopeObject()) { QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject())); if (value->isObject()) callData->thisObject = value; } - result = function.asFunctionObject()->call(callData); + result = f->as<QV4::FunctionObject>()->call(callData); if (scope.hasException()) { if (watcher.wasDeleted()) scope.engine->catchException(); // ignore exception @@ -223,7 +254,7 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, if (!errorString) { errorString = new QStringList; QString preamble = QLatin1String("QQmlExpression: Expression ") + - expression->m_vtable->expressionIdentifier(expression) + + expression->expressionIdentifier() + QLatin1String(" depends on non-NOTIFYable properties:"); errorString->append(preamble); } @@ -258,25 +289,26 @@ void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, void QQmlJavaScriptExpression::clearError() { - if (m_vtable.hasValue()) { - m_vtable.value().clearError(); - m_vtable.value().removeError(); - } + if (m_error) + delete m_error; + m_error = 0; } QQmlError QQmlJavaScriptExpression::error(QQmlEngine *engine) const { Q_UNUSED(engine); - if (m_vtable.hasValue()) - return m_vtable.constValue()->error(); + if (m_error) + return m_error->error(); else return QQmlError(); } QQmlDelayedError *QQmlJavaScriptExpression::delayedError() { - return &m_vtable.value(); + if (!m_error) + m_error = new QQmlDelayedError; + return m_error; } QV4::ReturnedValue @@ -358,7 +390,7 @@ void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **) QQmlJavaScriptExpression *expression = static_cast<QQmlJavaScriptExpressionGuard *>(e)->expression; - expression->m_vtable->expressionChanged(expression); + expression->expressionChanged(); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 989d5a0b0d..f846b6570f 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -89,23 +89,17 @@ private: QQmlDelayedError **prevError; }; -class QQmlJavaScriptExpression +class Q_QML_PRIVATE_EXPORT QQmlJavaScriptExpression { public: - // Although this looks crazy, we implement our own "vtable" here, rather than relying on - // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage - // location that is use for the vtable to also store the rarely used delayed error. - // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in - // memory for every expression. - struct VTable { - QString (*expressionIdentifier)(QQmlJavaScriptExpression *); - void (*expressionChanged)(QQmlJavaScriptExpression *); - }; + QQmlJavaScriptExpression(); + virtual ~QQmlJavaScriptExpression(); - QQmlJavaScriptExpression(VTable *vtable); + virtual QString expressionIdentifier() = 0; + virtual void expressionChanged() = 0; - QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, bool *isUndefined); - QV4::ReturnedValue evaluate(QQmlContextData *, const QV4::Value &function, QV4::CallData *callData, bool *isUndefined); + QV4::ReturnedValue evaluate(bool *isUndefined); + QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined); inline bool notifyOnValueChanged() const; @@ -115,6 +109,13 @@ public: inline QObject *scopeObject() const; inline void setScopeObject(QObject *v); + bool isValid() const { return context() != 0; } + + QQmlContextData *context() const { return m_context; } + void setContext(QQmlContextData *context); + + virtual void refresh(); + class DeleteWatcher { public: inline DeleteWatcher(QQmlJavaScriptExpression *); @@ -143,10 +144,9 @@ public: const QString &code, const QString &filename, quint16 line, QV4::PersistentValue *qmlscope = 0); -protected: - ~QQmlJavaScriptExpression(); private: + friend class QQmlContextData; typedef QQmlJavaScriptExpressionGuard Guard; friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **); @@ -169,13 +169,20 @@ private: QStringList *errorString; }; - QPointerValuePair<VTable, QQmlDelayedError> m_vtable; + QQmlDelayedError *m_error; // We store some flag bits in the following flag pointers. // activeGuards:flag1 - notifyOnValueChanged // activeGuards:flag2 - useSharedContext QBiPointer<QObject, DeleteWatcher> m_scopeObject; QForwardFieldList<Guard, &Guard::next> activeGuards; + + QQmlContextData *m_context; + QQmlJavaScriptExpression **m_prevExpression; + QQmlJavaScriptExpression *m_nextExpression; + +protected: + QV4::PersistentValue m_function; }; QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e) @@ -222,12 +229,12 @@ void QQmlJavaScriptExpression::setScopeObject(QObject *v) bool QQmlJavaScriptExpression::hasError() const { - return m_vtable.hasValue() && m_vtable.constValue()->isValid(); + return m_error && m_error->isValid(); } bool QQmlJavaScriptExpression::hasDelayedError() const { - return m_vtable.hasValue(); + return m_error; } QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e) diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index bcb1e72f0b..32a5b36fbb 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -92,10 +92,10 @@ QVariant QmlListWrapper::toVariant() const } -ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QmlListWrapper>()); - QmlListWrapper *w = static_cast<QmlListWrapper *>(m); + const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m); QV4::ExecutionEngine *v4 = w->engine(); if (name->equals(v4->id_length) && !w->d()->object.isNull()) { @@ -110,12 +110,12 @@ ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty) return Object::get(m, name, hasProperty); } -ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *hasProperty) { Q_UNUSED(hasProperty); Q_ASSERT(m->as<QmlListWrapper>()); - QmlListWrapper *w = static_cast<QmlListWrapper *>(m); + const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m); QV4::ExecutionEngine *v4 = w->engine(); quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0; diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index 3590bcb1c9..7e305b9e43 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -50,7 +50,7 @@ #include <QtQml/qqmllist.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4object_p.h> QT_BEGIN_NAMESPACE @@ -81,8 +81,8 @@ struct Q_QML_EXPORT QmlListWrapper : Object QVariant toVariant() const; - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes); }; diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 62b5b76ede..7f49798da6 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -65,13 +65,13 @@ static bool isLocaleObject(const QV4::Value &val) void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine) { - engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); - engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString); - engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString); - engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); - engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString); - engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString); - engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated); + engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); + engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString); + engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString); + engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); + engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString); + engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString); + engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), method_timeZoneUpdated); } QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx) @@ -81,7 +81,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct QV4::Scope scope(ctx); - QV4::DateObject *date = ctx->thisObject().asDateObject(); + QV4::DateObject *date = ctx->thisObject().as<DateObject>(); if (!date) return QV4::DatePrototype::method_toLocaleString(ctx); @@ -125,7 +125,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext QV4::Scope scope(ctx); - QV4::DateObject *date = ctx->thisObject().asDateObject(); + QV4::DateObject *date = ctx->thisObject().as<DateObject>(); if (!date) return QV4::DatePrototype::method_toLocaleTimeString(ctx); @@ -170,7 +170,7 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext QV4::Scope scope(ctx); - QV4::DateObject *dateObj = ctx->thisObject().asDateObject(); + QV4::DateObject *dateObj = ctx->thisObject().as<DateObject>(); if (!dateObj) return QV4::DatePrototype::method_toLocaleDateString(ctx); @@ -347,9 +347,9 @@ QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *c void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine) { - engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); - engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString); - engine->numberCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); + engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); + engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString); + engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString); } QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx) @@ -815,15 +815,15 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale) void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine) { - engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare); + engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare); } QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx) { - if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].asStringObject())) + if (ctx->argc() != 1 || (!ctx->args()[0].isString() && !ctx->args()[0].as<StringObject>())) return QV4::StringPrototype::method_localeCompare(ctx); - if (!ctx->thisObject().isString() && !ctx->thisObject().asStringObject()) + if (!ctx->thisObject().isString() && !ctx->thisObject().as<StringObject>()) return QV4::StringPrototype::method_localeCompare(ctx); QString thisString = ctx->thisObject().toQStringNoThrow(); diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index d4436482cf..d035544329 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -137,7 +137,7 @@ struct QQmlLocaleData : public QV4::Object V4_NEEDS_DESTROY static QLocale *getThisLocale(QV4::CallContext *ctx) { - QV4::Object *o = ctx->thisObject().asObject(); + QV4::Object *o = ctx->thisObject().as<Object>(); QQmlLocaleData *thisObject = o ? o->as<QQmlLocaleData>() : 0; if (!thisObject) { ctx->engine()->throwTypeError(); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 2f7834fa41..2947a03a4a 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1437,8 +1437,8 @@ bool QQmlMetaType::isAnyModule(const QString &uri) QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin(); - iter != data->uriToModule.end(); ++iter) { + for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.cbegin(); + iter != data->uriToModule.cend(); ++iter) { if ((*iter)->module() == uri) return true; } @@ -1715,7 +1715,7 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name); - while (it != data->nameToType.end() && it.key() == name) { + while (it != data->nameToType.cend() && it.key() == name) { // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty if (version_major < 0 || module.isEmpty() || (*it)->availableInVersion(module, version_major,version_minor)) return (*it); @@ -1749,7 +1749,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject); - while (it != data->metaObjectToType.end() && it.key() == metaObject) { + while (it != data->metaObjectToType.cend() && it.key() == metaObject) { QQmlType *t = *it; if (version_major < 0 || module.isEmpty() || t->availableInVersion(module, version_major,version_minor)) return t; @@ -1820,8 +1820,8 @@ QList<QString> QQmlMetaType::qmlTypeNames() QQmlMetaTypeData *data = metaTypeData(); QList<QString> names; - QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin(); - while (it != data->nameToType.end()) { + QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin(); + while (it != data->nameToType.cend()) { names += (*it)->qmlTypeName(); ++it; } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 3c2f3690b9..38268528c9 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -62,14 +62,6 @@ struct ActiveOCRestorer }; } -static void removeBindingOnProperty(QObject *o, int index) -{ - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); - QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0); - if (binding) binding->destroy(); -} - QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlContextData *creationContext, void *activeVMEDataForRootContext) : phase(Startup) , compiledData(compiledData) @@ -660,15 +652,12 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip) // ### this is best done through type-compile-time binding skip lists. if (_valueTypeProperty) { - QQmlAbstractBinding *binding = - QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1); + QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex); if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) { - QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0); - binding->destroy(); + QQmlPropertyPrivate::removeBinding(_bindingTarget, _valueTypeProperty->coreIndex, QQmlPropertyPrivate::DestroyOldBinding); } else if (binding) { - QQmlValueTypeProxyBinding *proxy = - static_cast<QQmlValueTypeProxyBinding *>(binding); + QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding); if (qmlTypeForObject(_bindingTarget)) { quint32 bindingSkipList = 0; @@ -800,7 +789,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment) && !_valueTypeProperty) - removeBindingOnProperty(_bindingTarget, property->coreIndex); + QQmlPropertyPrivate::removeBinding(_bindingTarget, property->coreIndex, QQmlPropertyPrivate::DestroyOldBinding); if (binding->type == QV4::CompiledData::Binding::Type_Script) { QV4::Function *runtimeFunction = compiledData->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; @@ -831,15 +820,10 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con sharedState->allCreatedBindings.push(qmlBinding); qmlBinding->m_mePtr = &sharedState->allCreatedBindings.top(); - qmlBinding->setTarget(_bindingTarget, targetCorePropertyData, context); + qmlBinding->setTarget(_bindingTarget, targetCorePropertyData); if (targetCorePropertyData.isAlias()) { - QQmlAbstractBinding *old = - QQmlPropertyPrivate::setBindingNoEnable(_bindingTarget, - targetCorePropertyData.coreIndex, - targetCorePropertyData.getValueTypeCoreIndex(), - qmlBinding); - if (old) { old->destroy(); } + QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable|QQmlPropertyPrivate::DestroyOldBinding); } else { qmlBinding->addToObject(); @@ -1124,7 +1108,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QBitArray bindingsToSkip; if (customParser) { - QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.find(index); + QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index); if (customParserBindings != compiledData->customParserBindings.constEnd()) { customParser->imports = compiledData->importCache; @@ -1187,9 +1171,9 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru if (!b) continue; b->m_mePtr = 0; - QQmlData *data = QQmlData::get(b->object()); + QQmlData *data = QQmlData::get(b->targetObject()); Q_ASSERT(data); - data->clearPendingBindingBit(b->propertyIndex()); + data->clearPendingBindingBit(b->targetPropertyIndex()); b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); @@ -1299,7 +1283,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * QBitArray bindingSkipList = bindingsToSkip; { - QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.find(_compiledObjectIndex); + QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.constFind(_compiledObjectIndex); if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) { if (bindingSkipList.isEmpty()) bindingSkipList.resize(deferredBindings->count()); diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index fc24b15fd2..c6d2d44ee1 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -277,8 +277,8 @@ void QQmlOpenMetaObject::setValue(int id, const QVariant &value) QVariant QQmlOpenMetaObject::value(const QByteArray &name) const { - QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name); - if (iter == d->type->d->names.end()) + QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name); + if (iter == d->type->d->names.cend()) return QVariant(); return d->getData(*iter); @@ -286,8 +286,8 @@ QVariant QQmlOpenMetaObject::value(const QByteArray &name) const QVariant &QQmlOpenMetaObject::operator[](const QByteArray &name) { - QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name); - Q_ASSERT(iter != d->type->d->names.end()); + QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name); + Q_ASSERT(iter != d->type->d->names.cend()); return d->getData(*iter); } @@ -299,10 +299,10 @@ QVariant &QQmlOpenMetaObject::operator[](int id) bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val) { - QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name); + QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name); int id = -1; - if (iter == d->type->d->names.end()) { + if (iter == d->type->d->names.cend()) { id = createProperty(name.constData(), "") - d->type->d->propertyOffset; } else { id = *iter; diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index ae452b727e..54dfd3aa27 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -55,6 +55,7 @@ #include <private/qmetaobject_p.h> #include <private/qqmlvaluetypewrapper_p.h> #include <QtCore/qdebug.h> +#include <cmath> Q_DECLARE_METATYPE(QList<int>) Q_DECLARE_METATYPE(QList<qreal>) @@ -699,8 +700,7 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that) if (!that.d || !that.isProperty() || !that.d->object) return 0; - return binding(that.d->object, that.d->core.coreIndex, - that.d->core.getValueTypeCoreIndex()); + return binding(that.d->object, that.d->core.encodedIndex()); } /*! @@ -716,61 +716,97 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that) \a flags is passed through to the binding and is used for the initial update (when the binding sets the initial value, it will use these flags for the write). */ -QQmlAbstractBinding * -QQmlPropertyPrivate::setBinding(const QQmlProperty &that, - QQmlAbstractBinding *newBinding, - WriteFlags flags) +void +QQmlPropertyPrivate::setBinding(const QQmlProperty &that, QQmlAbstractBinding *newBinding) { + if (!newBinding) { + removeBinding(that); + return; + } + if (!that.d || !that.isProperty() || !that.d->object) { - if (newBinding) - newBinding->destroy(); - return 0; + newBinding->destroy(); + return; } + setBinding(newBinding); +} - if (newBinding) { - // In the case that the new binding is provided, we must target the property it - // is associated with. If we don't do this, retargetBinding() can fail. - QObject *object = newBinding->object(); - int pi = newBinding->propertyIndex(); +static QQmlAbstractBinding *removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::BindingFlags flags) +{ + int coreIndex; + int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); - int core; - int vt = QQmlPropertyData::decodeValueTypePropertyIndex(pi, &core); + QQmlData *data = QQmlData::get(object, false); - return setBinding(object, core, vt, newBinding, flags); - } else { - return setBinding(that.d->object, that.d->core.coreIndex, - that.d->core.getValueTypeCoreIndex(), - newBinding, flags); + if (!data || !data->hasBindingBit(coreIndex)) + return 0; + + QQmlAbstractBinding *oldBinding = data->bindings; + + while (oldBinding && oldBinding->targetPropertyIndex() != coreIndex) + oldBinding = oldBinding->nextBinding(); + + if (!oldBinding) + return 0; + + if (valueTypeIndex != -1 && oldBinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) + oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding)->binding(index); + + if (!oldBinding) + return 0; + + oldBinding->removeFromObject(); + if (!(flags & QQmlPropertyPrivate::DontEnable)) + oldBinding->setEnabled(false, 0); + + if (flags & QQmlPropertyPrivate::DestroyOldBinding) { + oldBinding->destroy(); + return 0; } + + return oldBinding; +} + +QQmlAbstractBinding *QQmlPropertyPrivate::removeBinding(QQmlAbstractBinding *b, QQmlPropertyPrivate::BindingFlag flags) +{ + return removeBinding(b->targetObject(), b->targetPropertyIndex(), flags); +} + +QQmlAbstractBinding *QQmlPropertyPrivate::removeBinding(QObject *o, int index, QQmlPropertyPrivate::BindingFlag flags) +{ + Q_ASSERT(o); + + QObject *target; + int targetIndex; + findAliasTarget(o, index, &target, &targetIndex); + return removeOldBinding(target, targetIndex, flags); +} + +QQmlAbstractBinding *QQmlPropertyPrivate::removeBinding(const QQmlProperty &that, BindingFlag flags) +{ + if (!that.d || !that.isProperty() || !that.d->object) + return 0; + + return removeBinding(that.d->object, that.d->core.encodedIndex(), flags); } QQmlAbstractBinding * -QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex) +QQmlPropertyPrivate::binding(QObject *object, int index) { QQmlData *data = QQmlData::get(object); if (!data) return 0; - QQmlPropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex); - - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1) - return 0; + findAliasTarget(object, index, &object, &index); - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex; - return binding(aObject, aCoreIndex, aValueTypeIndex); - } + int coreIndex; + int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); if (!data->hasBindingBit(coreIndex)) return 0; QQmlAbstractBinding *binding = data->bindings; - while (binding && binding->propertyIndex() != coreIndex) + while (binding && binding->targetPropertyIndex() != coreIndex) binding = binding->nextBinding(); if (binding && valueTypeIndex != -1) { @@ -786,11 +822,11 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex) void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex, QObject **targetObject, int *targetBindingIndex) { - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex); - QQmlData *data = QQmlData::get(object, false); if (data) { + int coreIndex; + int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex); + QQmlPropertyData *propertyData = data->propertyCache?data->propertyCache->property(coreIndex):0; if (propertyData && propertyData->isAlias()) { @@ -817,119 +853,30 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex, *targetBindingIndex = bindingIndex; } -QQmlAbstractBinding * -QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex, - QQmlAbstractBinding *newBinding, WriteFlags flags) -{ - QQmlData *data = QQmlData::get(object, 0 != newBinding); - QQmlAbstractBinding *binding = 0; - if (data) { - QQmlPropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex); - - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { - if (newBinding) newBinding->destroy(); - return 0; - } - - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex; - return setBinding(aObject, aCoreIndex, aValueTypeIndex, newBinding, flags); - } - } - - if (data && data->hasBindingBit(coreIndex)) { - binding = data->bindings; - - while (binding && binding->propertyIndex() != coreIndex) - binding = binding->nextBinding(); - } - - int index = coreIndex; - if (valueTypeIndex != -1) - index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex); - - if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) - binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index); - - if (binding) { - binding->removeFromObject(); - binding->setEnabled(false, 0); - } - - if (newBinding) { - if (newBinding->propertyIndex() != index || newBinding->object() != object) - newBinding->retargetBinding(object, index); - - Q_ASSERT(newBinding->propertyIndex() == index); - Q_ASSERT(newBinding->object() == object); - - newBinding->addToObject(); - newBinding->setEnabled(true, flags); - } - - return binding; -} - -QQmlAbstractBinding * -QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valueTypeIndex, - QQmlAbstractBinding *newBinding) +void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags flags, WriteFlags writeFlags) { - QQmlData *data = QQmlData::get(object, 0 != newBinding); - QQmlAbstractBinding *binding = 0; - - if (data) { - QQmlPropertyData *propertyData = - data->propertyCache?data->propertyCache->property(coreIndex):0; - if (propertyData && propertyData->isAlias()) { - QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex); + Q_ASSERT(binding); - QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { - if (newBinding) newBinding->destroy(); - return 0; - } + QObject *object = binding->targetObject(); + int index = binding->targetPropertyIndex(); - // This will either be a value type sub-reference or an alias to a value-type sub-reference not both - Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - aValueTypeIndex = (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex; - return setBindingNoEnable(aObject, aCoreIndex, aValueTypeIndex, newBinding); - } - } - - if (data && data->hasBindingBit(coreIndex)) { - binding = data->bindings; - - while (binding && binding->propertyIndex() != coreIndex) - binding = binding->nextBinding(); +#ifndef QT_NO_DEBUG + int coreIndex; + QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); + QQmlData *data = QQmlData::get(object, true); + if (data->propertyCache) { + QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex); + Q_ASSERT(propertyData && !propertyData->isAlias()); } +#endif - int index = coreIndex; - if (valueTypeIndex != -1) - index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex); - - if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) - binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index); - - if (binding) - binding->removeFromObject(); - - if (newBinding) { - if (newBinding->propertyIndex() != index || newBinding->object() != object) - newBinding->retargetBinding(object, index); - - Q_ASSERT(newBinding->propertyIndex() == index); - Q_ASSERT(newBinding->object() == object); + removeOldBinding(object, index, flags); - newBinding->addToObject(); - } + binding->addToObject(); + if (!(flags & DontEnable)) + binding->setEnabled(true, writeFlags); - return binding; } /*! @@ -1210,12 +1157,8 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object, QQmlContextData *context, WriteFlags flags) { // Remove any existing bindings on this property - if (!(flags & DontRemoveBinding) && object) { - QQmlAbstractBinding *binding = setBinding(object, core.coreIndex, - core.getValueTypeCoreIndex(), - 0, flags); - if (binding) binding->destroy(); - } + if (!(flags & DontRemoveBinding) && object) + removeBinding(object, core.encodedIndex(), DestroyOldBinding); bool rv = false; if (core.isValueTypeVirtual()) { @@ -1255,7 +1198,7 @@ bool QQmlPropertyPrivate::write(QObject *object, // Enum values come through the script engine as doubles if (value.userType() == QVariant::Double) { double integral; - double fractional = modf(value.toDouble(), &integral); + double fractional = std::modf(value.toDouble(), &integral); if (qFuzzyIsNull(fractional)) v.convert(QVariant::Int); } @@ -1551,7 +1494,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, if (expression->hasError()) { return false; } else if (isVarProperty) { - QV4::FunctionObject *f = result.asFunctionObject(); + const QV4::FunctionObject *f = result.as<QV4::FunctionObject>(); if (f && f->isBinding()) { // we explicitly disallow this case to avoid confusion. Users can still store one // in an array in a var property if they need to, but the common case is user error. @@ -1569,7 +1512,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, } else if (isUndefined && type == qMetaTypeId<QVariant>()) { writeValueProperty(object, core, QVariant(), context, flags); } else if (type == qMetaTypeId<QJSValue>()) { - QV4::FunctionObject *f = result.asFunctionObject(); + const QV4::FunctionObject *f = result.as<QV4::FunctionObject>(); if (f && f->isBinding()) { expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration.")); expression->delayedError()->setErrorObject(object); @@ -1587,7 +1530,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, expression->delayedError()->setErrorDescription(errorStr); expression->delayedError()->setErrorObject(object); return false; - } else if (QV4::FunctionObject *f = result.asFunctionObject()) { + } else if (const QV4::FunctionObject *f = result.as<QV4::FunctionObject>()) { if (f->isBinding()) expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration.")); else diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h index 98e310ebce..7bbb600ade 100644 --- a/src/qml/qml/qqmlproperty_p.h +++ b/src/qml/qml/qqmlproperty_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE class QQmlContext; class QQmlEnginePrivate; class QQmlJavaScriptExpression; + class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount { public: @@ -103,15 +104,19 @@ public: QQmlContextData *, WriteFlags flags = 0); static void findAliasTarget(QObject *, int, QObject **, int *); - static QQmlAbstractBinding *setBinding(QObject *, int coreIndex, - int valueTypeIndex /* -1 */, - QQmlAbstractBinding *, - WriteFlags flags = DontRemoveBinding); - static QQmlAbstractBinding *setBindingNoEnable(QObject *, int coreIndex, - int valueTypeIndex /* -1 */, - QQmlAbstractBinding *); - static QQmlAbstractBinding *binding(QObject *, int coreIndex, - int valueTypeIndex /* -1 */); + enum BindingFlag { + None = 0, + DestroyOldBinding = 0x1, + DontEnable = 0x2 + }; + Q_DECLARE_FLAGS(BindingFlags, BindingFlag) + + static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, WriteFlags writeFlags = DontRemoveBinding); + + static QQmlAbstractBinding *removeBinding(const QQmlProperty &that, BindingFlag flag = None); + static QQmlAbstractBinding *removeBinding(QObject *o, int index, QQmlPropertyPrivate::BindingFlag flags = None); + static QQmlAbstractBinding *removeBinding(QQmlAbstractBinding *b, BindingFlag flag = None); + static QQmlAbstractBinding *binding(QObject *, int index); static QQmlPropertyData saveValueType(const QQmlPropertyData &, const QMetaObject *, int, @@ -128,9 +133,7 @@ public: // "Public" (to QML) methods static QQmlAbstractBinding *binding(const QQmlProperty &that); - static QQmlAbstractBinding *setBinding(const QQmlProperty &that, - QQmlAbstractBinding *, - WriteFlags flags = DontRemoveBinding); + static void setBinding(const QQmlProperty &that, QQmlAbstractBinding *); static QQmlBoundSignalExpression *signalExpression(const QQmlProperty &that); static QQmlBoundSignalExpressionPointer setSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *); @@ -153,6 +156,7 @@ public: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::WriteFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::BindingFlags) QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index dd1f93ec00..168d038f9e 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -42,7 +42,7 @@ #include <private/qqmlaccessors_p.h> #include <private/qmetaobjectbuilder_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <QtCore/qdebug.h> diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 6ed9ec0d36..4d8c6dd9a5 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -54,7 +54,7 @@ #include <QtCore/qvarlengtharray.h> #include <QtCore/qvector.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QT_BEGIN_NAMESPACE @@ -174,7 +174,6 @@ public: int propType; // When !NotFullyResolved const char *propTypeName; // When NotFullyResolved }; - int coreIndex; union { // The notify index is in the range returned by QObjectPrivate::signalIndex(). // This is different from QMetaMethod::methodIndex(). @@ -208,6 +207,7 @@ public: qintptr accessorData; }; }; + int coreIndex; private: friend class QQmlPropertyData; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index d9ea273698..5be478fa65 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -60,7 +60,7 @@ #include <private/qflagpointer_p.h> #include <private/qqmlirbuilder_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4script_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp index d0658f2c3c..23cc12c895 100644 --- a/src/qml/qml/qqmltypenamecache.cpp +++ b/src/qml/qml/qqmltypenamecache.cpp @@ -125,7 +125,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons const Import *i = static_cast<const Import *>(importNamespace); Q_ASSERT(i->scriptIndex == -1); - QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.find(i); + QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.constFind(i); if (it != m_namespacedImports.constEnd()) { Result r = query(*it, name); if (r.isValid()) diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 8a2118ef27..3d22b0b38f 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -124,14 +124,14 @@ ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, Q } -ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QmlTypeWrapper>()); - QV4::ExecutionEngine *v4 = static_cast<QmlTypeWrapper *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine(); QV4::Scope scope(v4); - Scoped<QmlTypeWrapper> w(scope, static_cast<QmlTypeWrapper *>(m)); + Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m)); if (hasProperty) *hasProperty = true; diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 660d2836ff..14741a5bad 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -48,7 +48,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qpointer.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4object_p.h> QT_BEGIN_NAMESPACE @@ -94,7 +94,7 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums); - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); static PropertyAttributes query(const Managed *, String *name); static bool isEqualTo(Managed *that, Managed *o); diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp index cfc9b196d2..f0457d25e3 100644 --- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp +++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp @@ -35,17 +35,6 @@ QT_BEGIN_NAMESPACE -// Used in qqmlabstractbinding.cpp -QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable = { - QQmlAbstractBinding::default_destroy<QQmlValueTypeProxyBinding>, - QQmlAbstractBinding::default_expression, - QQmlValueTypeProxyBinding::propertyIndex, - QQmlValueTypeProxyBinding::object, - QQmlValueTypeProxyBinding::setEnabled, - QQmlValueTypeProxyBinding::update, - QQmlAbstractBinding::default_retargetBinding -}; - QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index) : QQmlAbstractBinding(ValueTypeProxy), m_object(o), m_index(index), m_bindings(0) { @@ -64,51 +53,20 @@ QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding() } } -void QQmlValueTypeProxyBinding::setEnabled(QQmlAbstractBinding *_This, - bool e, QQmlPropertyPrivate::WriteFlags flags) +void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) { - QQmlValueTypeProxyBinding *This = static_cast<QQmlValueTypeProxyBinding *>(_This); - - if (e) { - QQmlAbstractBinding *bindings = This->m_bindings; - This->recursiveEnable(bindings, flags); - } else { - QQmlAbstractBinding *bindings = This->m_bindings; - This->recursiveDisable(bindings); + QQmlAbstractBinding *b = m_bindings; + while (b) { + b->setEnabled(e, flags); + b = b->nextBinding(); } } -void QQmlValueTypeProxyBinding::recursiveEnable(QQmlAbstractBinding *b, QQmlPropertyPrivate::WriteFlags flags) -{ - if (!b) - return; - - recursiveEnable(b->nextBinding(), flags); - - if (b) - b->setEnabled(true, flags); -} - -void QQmlValueTypeProxyBinding::recursiveDisable(QQmlAbstractBinding *b) -{ - if (!b) - return; - - recursiveDisable(b->nextBinding()); - - if (b) - b->setEnabled(false, 0); -} - -void QQmlValueTypeProxyBinding::update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags) -{ -} - QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex) { QQmlAbstractBinding *binding = m_bindings; - while (binding && binding->propertyIndex() != propertyIndex) + while (binding && binding->targetPropertyIndex() != propertyIndex) binding = binding->nextBinding(); return binding; @@ -123,7 +81,7 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask) QQmlAbstractBinding *lastBinding = 0; while (binding) { - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->propertyIndex()); + int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->targetPropertyIndex()); if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) { QQmlAbstractBinding *remove = binding; binding = remove->nextBinding(); @@ -143,22 +101,12 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask) } } -int QQmlValueTypeProxyBinding::propertyIndex(const QQmlAbstractBinding *This) -{ - return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_index; -} - -QObject *QQmlValueTypeProxyBinding::object(const QQmlAbstractBinding *This) -{ - return static_cast<const QQmlValueTypeProxyBinding *>(This)->m_object; -} - -int QQmlValueTypeProxyBinding::propertyIndex() const +int QQmlValueTypeProxyBinding::targetPropertyIndex() const { return m_index; } -QObject *QQmlValueTypeProxyBinding::object() const +QObject *QQmlValueTypeProxyBinding::targetObject() const { return m_object; } diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h index 873fbb4af1..c73c944efd 100644 --- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h +++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h @@ -54,26 +54,17 @@ class QQmlValueTypeProxyBinding : public QQmlAbstractBinding public: QQmlValueTypeProxyBinding(QObject *o, int coreIndex); - int propertyIndex() const; - QObject *object() const; - - QQmlAbstractBinding *binding(int propertyIndex); - + QQmlAbstractBinding *binding(int targetPropertyIndex); void removeBindings(quint32 mask); - // "Inherited" from QQmlAbstractBinding - static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags); - static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); - static int propertyIndex(const QQmlAbstractBinding *); - static QObject *object(const QQmlAbstractBinding *); + virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags); + virtual int targetPropertyIndex() const; + virtual QObject *targetObject() const; protected: ~QQmlValueTypeProxyBinding(); private: - void recursiveEnable(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); - void recursiveDisable(QQmlAbstractBinding *); - friend class QQmlAbstractBinding; QObject *m_object; int m_index; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 67092438a7..b4d5faa4cf 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -292,7 +292,7 @@ bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) { - Object *o = ctx->thisObject().asObject(); + Object *o = ctx->thisObject().as<Object>(); if (!o) return ctx->engine()->throwTypeError(); QQmlValueTypeWrapper *w = o->as<QQmlValueTypeWrapper>(); @@ -325,14 +325,14 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx) return Encode(ctx->engine()->newString(result)); } -ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QQmlValueTypeWrapper>()); - QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m); + const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m); QV4::ExecutionEngine *v4 = r->engine(); // Note: readReferenceValue() can change the reference->type. - if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) { + if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) { if (!reference->readReferenceValue()) return Primitive::undefinedValue().asReturnedValue(); } @@ -408,45 +408,42 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) QMetaProperty property = metaObject->property(pd->coreIndex); Q_ASSERT(property.isValid()); - QQmlBinding *newBinding = 0; - - QV4::ScopedFunctionObject f(scope, value); - if (reference && f) { - if (!f->isBinding()) { - // assigning a JS function to a non-var-property is not allowed. - QString error = QStringLiteral("Cannot assign JavaScript function to value-type property"); - ScopedString e(scope, v4->newString(error)); - v4->throwError(e); - return; - } + if (reference) { + QV4::ScopedFunctionObject f(scope, value); + if (f) { + if (!f->isBinding()) { + // assigning a JS function to a non-var-property is not allowed. + QString error = QStringLiteral("Cannot assign JavaScript function to value-type property"); + ScopedString e(scope, v4->newString(error)); + v4->throwError(e); + return; + } - QQmlContextData *context = QmlContextWrapper::callingContext(v4); + QQmlContextData *context = QmlContextWrapper::callingContext(v4); - QQmlPropertyData cacheData; - cacheData.setFlags(QQmlPropertyData::IsWritable | - QQmlPropertyData::IsValueTypeVirtual); - cacheData.propType = writeBackPropertyType; - cacheData.coreIndex = reference->d()->property; - cacheData.valueTypeFlags = 0; - cacheData.valueTypeCoreIndex = pd->coreIndex; - cacheData.valueTypePropType = property.userType(); + QQmlPropertyData cacheData; + cacheData.setFlags(QQmlPropertyData::IsWritable | + QQmlPropertyData::IsValueTypeVirtual); + cacheData.propType = writeBackPropertyType; + cacheData.coreIndex = reference->d()->property; + cacheData.valueTypeFlags = 0; + cacheData.valueTypeCoreIndex = pd->coreIndex; + cacheData.valueTypePropType = property.userType(); - QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f); - bindingFunction->initBindingLocation(); + QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f); + bindingFunction->initBindingLocation(); - newBinding = new QQmlBinding(value, reference->d()->object, context); - newBinding->setTarget(reference->d()->object, cacheData, context); - } + QQmlBinding *newBinding = new QQmlBinding(value, reference->d()->object, context); + newBinding->setTarget(reference->d()->object, cacheData); + QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::DestroyOldBinding); + return; + } else { + QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyData::encodeValueTypePropertyIndex(reference->d()->property, pd->coreIndex), + QQmlPropertyPrivate::DestroyOldBinding); - if (reference) { - QQmlAbstractBinding *oldBinding = - QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding); - if (oldBinding) - oldBinding->destroy(); + } } - if (newBinding) - return; QVariant v = v4->toVariant(value, property.userType()); diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index cad48e661c..5f0edfb71d 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -48,7 +48,7 @@ #include <QtCore/qglobal.h> #include <private/qtqmlglobal_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4object_p.h> QT_BEGIN_NAMESPACE @@ -89,7 +89,7 @@ public: int typeId() const; bool write(QObject *target, int propertyIndex) const; - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); static void put(Managed *m, String *name, const Value &value); static bool isEqualTo(Managed *m, Managed *other); static PropertyAttributes query(const Managed *, String *name); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 5b1be15869..15017a2572 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -874,10 +874,8 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) int flags = *reinterpret_cast<int*>(a[3]); if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) { QQmlData *targetData = QQmlData::get(target); - if (targetData && targetData->hasBindingBit(d->propertyIndex())) { - QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0); - if (binding) binding->destroy(); - } + if (targetData && targetData->hasBindingBit(d->propertyIndex())) + QQmlPropertyPrivate::removeBinding(target, d->propertyIdx, QQmlPropertyPrivate::DestroyOldBinding); } } @@ -1183,7 +1181,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function) v8methods = new QV4::PersistentValue[metaData->methodCount]; int methodIndex = index - methodOffset() - plainSignals; - v8methods[methodIndex].set(function.asObject()->engine(), function); + v8methods[methodIndex].set(function.as<QV4::Object>()->engine(), function); } QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) @@ -1251,7 +1249,7 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) void QQmlVMEMetaObject::allocateVarPropertiesArray() { QQmlEngine *qml = qmlEngine(object); - assert(qml); + Q_ASSERT(qml); QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle()); QV4::Scope scope(v4); varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount)); diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index d0e2e34ff1..44809a26f0 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -63,7 +63,7 @@ #include <private/qv8engine_p.h> #include <private/qflagpointer_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 2a3ede6a22..fd06ff4654 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -60,6 +60,7 @@ #include <private/qv4objectproto_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qv4arraybuffer_p.h> +#include <private/qv4jsonobject_p.h> using namespace QV4; @@ -222,8 +223,8 @@ public: static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &); // JS API - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); }; Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list) @@ -244,8 +245,8 @@ public: V4_NEEDS_DESTROY // JS API - static ReturnedValue get(Managed *m, String *name, bool *hasProperty); - static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); + static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); // C++ API static ReturnedValue create(ExecutionEngine *, NodeImpl *); @@ -871,10 +872,10 @@ bool Node::isNull() const return d()->d == 0; } -ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasProperty) { Q_ASSERT(m->as<NamedNodeMap>()); - NamedNodeMap *r = static_cast<NamedNodeMap *>(m); + const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m); QV4::ExecutionEngine *v4 = r->engine(); if ((int)index < r->d()->list.count()) { @@ -887,10 +888,10 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty return Encode::undefined(); } -ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<NamedNodeMap>()); - NamedNodeMap *r = static_cast<NamedNodeMap *>(m); + const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m); QV4::ExecutionEngine *v4 = r->engine(); name->makeIdentifier(v4); @@ -916,10 +917,10 @@ ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QL return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue(); } -ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty) +ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty) { Q_ASSERT(m->as<NodeList>()); - NodeList *r = static_cast<NodeList *>(m); + const NodeList *r = static_cast<const NodeList *>(m); QV4::ExecutionEngine *v4 = r->engine(); if ((int)index < r->d()->d->children.count()) { @@ -932,10 +933,10 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty) return Encode::undefined(); } -ReturnedValue NodeList::get(Managed *m, String *name, bool *hasProperty) +ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<NodeList>()); - NodeList *r = static_cast<NodeList *>(m); + const NodeList *r = static_cast<const NodeList *>(m); QV4::ExecutionEngine *v4 = r->engine(); name->makeIdentifier(v4); @@ -1026,6 +1027,8 @@ public: const QString & responseType() const; void setResponseType(const QString &); + + QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*); private slots: void readyRead(); void error(QNetworkReply::NetworkError); @@ -1076,6 +1079,7 @@ private: QNetworkAccessManager *networkAccessManager() { return m_nam; } QString m_responseType; + QV4::PersistentValue m_parsedJson; }; QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager) @@ -1083,6 +1087,7 @@ QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessMa , m_state(Unsent), m_errorFlag(false), m_sendFlag(false) , m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager) , m_responseType() + , m_parsedJson() { } @@ -1478,6 +1483,24 @@ void QQmlXMLHttpRequest::setResponseType(const QString &responseType) m_responseType = responseType; } +QV4::ReturnedValue QQmlXMLHttpRequest::jsonResponseBody(QV4::ExecutionEngine* engine) +{ + if (m_parsedJson.isEmpty()) { + Scope scope(engine); + + QJsonParseError error; + const QString& jtext = responseBody(); + JsonParser parser(scope.engine, jtext.constData(), jtext.length()); + ScopedValue jsonObject(scope, parser.parse(&error)); + if (error.error != QJsonParseError::NoError) + return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error")); + + m_parsedJson.set(scope.engine, jsonObject); + } + + return m_parsedJson.value(); +} + #ifndef QT_NO_TEXTCODEC QTextCodec* QQmlXMLHttpRequest::findTextCodec() const @@ -1599,7 +1622,7 @@ struct QQmlXMLHttpRequestWrapper : Object { struct QQmlXMLHttpRequestCtor : FunctionObject { QQmlXMLHttpRequestCtor(ExecutionEngine *engine); - Object *proto; + Pointer<Object> proto; }; } @@ -1625,9 +1648,9 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject c->proto->mark(e); FunctionObject::markObjects(that, e); } - static ReturnedValue construct(Managed *that, QV4::CallData *) + static ReturnedValue construct(const Managed *that, QV4::CallData *) { - Scope scope(static_cast<QQmlXMLHttpRequestCtor *>(that)->engine()); + Scope scope(static_cast<const QQmlXMLHttpRequestCtor *>(that)->engine()); Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>()); if (!ctor) return scope.engine->throwTypeError(); @@ -1639,7 +1662,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject return w.asReturnedValue(); } - static ReturnedValue call(Managed *, QV4::CallData *) { + static ReturnedValue call(const Managed *, QV4::CallData *) { return Primitive::undefinedValue().asReturnedValue(); } @@ -1986,6 +2009,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx) return QV4::Encode(scope.engine->newString(r->responseBody())); } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) { return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody())); + } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) { + return r->jsonResponseBody(scope.engine); } else { return QV4::Encode(scope.engine->newString(QString())); } @@ -2033,7 +2058,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4) Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4)); ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest"))); - v4->globalObject()->defineReadonlyProperty(s, ctor); + v4->globalObject->defineReadonlyProperty(s, ctor); QQmlXMLHttpRequestData *data = new QQmlXMLHttpRequestData; return data; diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index f53b9a0c7d..17dfeea168 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -51,6 +51,7 @@ #include <private/qv4include_p.h> #include <private/qv4context_p.h> #include <private/qv4stringobject_p.h> +#include <private/qv4dateobject_p.h> #include <private/qv4mm_p.h> #include <private/qv4jsonobject_p.h> #include <private/qv4objectproto_p.h> @@ -669,7 +670,7 @@ ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx) QVariant argVariant = ctx->engine()->toVariant(ctx->args()[0], -1); QTime time; - if (ctx->args()[0].asDateObject() || (argVariant.type() == QVariant::String)) + if (ctx->args()[0].as<DateObject>() || (argVariant.type() == QVariant::String)) time = argVariant.toDateTime().time(); else // if (argVariant.type() == QVariant::Time), or invalid. time = argVariant.toTime(); @@ -1178,7 +1179,7 @@ ReturnedValue QtObject::method_locale(CallContext *ctx) return QQmlLocale::locale(ctx->engine(), code); } -Heap::QQmlBindingFunction::QQmlBindingFunction(QV4::FunctionObject *originalFunction) +Heap::QQmlBindingFunction::QQmlBindingFunction(const QV4::FunctionObject *originalFunction) : QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name()) , originalFunction(originalFunction->d()) { @@ -1191,10 +1192,10 @@ void QQmlBindingFunction::initBindingLocation() d()->bindingLocation.line = frame.line; } -ReturnedValue QQmlBindingFunction::call(Managed *that, CallData *callData) +ReturnedValue QQmlBindingFunction::call(const Managed *that, CallData *callData) { - Scope scope(static_cast<QQmlBindingFunction*>(that)->engine()); - ScopedFunctionObject function(scope, static_cast<QQmlBindingFunction*>(that)->d()->originalFunction); + Scope scope(static_cast<const QQmlBindingFunction*>(that)->engine()); + ScopedFunctionObject function(scope, static_cast<const QQmlBindingFunction*>(that)->d()->originalFunction); return function->call(callData); } @@ -1256,7 +1257,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx) { if (ctx->argc() != 1) V4THROW_ERROR("binding() requires 1 argument"); - QV4::FunctionObject *f = ctx->args()[0].asFunctionObject(); + const QV4::FunctionObject *f = ctx->args()[0].as<FunctionObject>(); if (!f) V4THROW_TYPE("binding(): argument (binding expression) must be a function"); @@ -1267,7 +1268,7 @@ ReturnedValue QtObject::method_binding(CallContext *ctx) ReturnedValue QtObject::method_get_platform(CallContext *ctx) { // ### inefficient. Should be just a value based getter - Object *o = ctx->thisObject().asObject(); + Object *o = ctx->thisObject().as<Object>(); if (!o) return ctx->engine()->throwTypeError(); QtObject *qt = o->as<QtObject>(); @@ -1284,7 +1285,7 @@ ReturnedValue QtObject::method_get_platform(CallContext *ctx) ReturnedValue QtObject::method_get_application(CallContext *ctx) { // ### inefficient. Should be just a value based getter - Object *o = ctx->thisObject().asObject(); + Object *o = ctx->thisObject().as<Object>(); if (!o) return ctx->engine()->throwTypeError(); QtObject *qt = o->as<QtObject>(); @@ -1379,7 +1380,7 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c if (i != 0) result.append(QLatin1Char(' ')); - if (ctx->args()[i].asArrayObject()) + if (ctx->args()[i].as<ArrayObject>()) result.append(QStringLiteral("[") + ctx->args()[i].toQStringNoThrow() + QStringLiteral("]")); else result.append(ctx->args()[i].toQStringNoThrow()); @@ -1612,7 +1613,7 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject) globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt); // string prototype extension - v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg); + v4->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg); } diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index b78375118b..bdd53fe601 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -68,8 +68,8 @@ struct ConsoleObject : Object { }; struct QQmlBindingFunction : FunctionObject { - QQmlBindingFunction(QV4::FunctionObject *originalFunction); - FunctionObject *originalFunction; + QQmlBindingFunction(const QV4::FunctionObject *originalFunction); + Pointer<FunctionObject> originalFunction; // Set when the binding is created later QQmlSourceLocation bindingLocation; }; @@ -166,7 +166,7 @@ struct QQmlBindingFunction : public QV4::FunctionObject void initBindingLocation(); // from caller stack trace - static ReturnedValue call(Managed *that, CallData *callData); + static ReturnedValue call(const Managed *that, CallData *callData); static void markObjects(Heap::Base *that, ExecutionEngine *e); }; diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp index c318e2e550..1baaa113aa 100644 --- a/src/qml/qml/v8/qv4domerrors.cpp +++ b/src/qml/qml/v8/qv4domerrors.cpp @@ -59,7 +59,7 @@ void qt_add_domexceptions(ExecutionEngine *e) domexception->defineReadonlyProperty(QStringLiteral("INVALID_ACCESS_ERR"), Primitive::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR)); domexception->defineReadonlyProperty(QStringLiteral("VALIDATION_ERR"), Primitive::fromInt32(DOMEXCEPTION_VALIDATION_ERR)); domexception->defineReadonlyProperty(QStringLiteral("TYPE_MISMATCH_ERR"), Primitive::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR)); - e->globalObject()->defineDefaultProperty(QStringLiteral("DOMException"), domexception); + e->globalObject->defineDefaultProperty(QStringLiteral("DOMException"), domexception); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv4sqlerrors.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp index b7a5b71540..c61e57560d 100644 --- a/src/qml/qml/v8/qv4sqlerrors.cpp +++ b/src/qml/qml/v8/qv4sqlerrors.cpp @@ -51,7 +51,7 @@ void qt_add_sqlexceptions(QV4::ExecutionEngine *engine) sqlexception->defineReadonlyProperty(QStringLiteral("SYNTAX_ERR"), Primitive::fromInt32(SQLEXCEPTION_SYNTAX_ERR)); sqlexception->defineReadonlyProperty(QStringLiteral("CONSTRAINT_ERR"), Primitive::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR)); sqlexception->defineReadonlyProperty(QStringLiteral("TIMEOUT_ERR"), Primitive::fromInt32(SQLEXCEPTION_TIMEOUT_ERR)); - engine->globalObject()->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception); + engine->globalObject->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index a7c63c9df1..be28b948f5 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -61,7 +61,7 @@ #include <QtCore/qdatastream.h> #include <private/qsimd_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4dateobject_p.h> #include <private/qv4objectiterator_p.h> #include <private/qv4mm_p.h> @@ -179,7 +179,7 @@ QQmlContextData *QV8Engine::callingContext() void QV8Engine::initializeGlobal() { QV4::Scope scope(m_v4Engine); - QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject()); + QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject); QQmlLocale::registerStringLocaleCompare(m_v4Engine); QQmlDateExtension::registerExtension(m_v4Engine); @@ -191,9 +191,9 @@ void QV8Engine::initializeGlobal() qt_add_sqlexceptions(m_v4Engine); { - for (uint i = 0; i < m_v4Engine->globalObject()->internalClass()->size; ++i) { - if (m_v4Engine->globalObject()->internalClass()->nameMap.at(i)) - m_illegalNames.insert(m_v4Engine->globalObject()->internalClass()->nameMap.at(i)->string); + for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) { + if (m_v4Engine->globalObject->internalClass()->nameMap.at(i)) + m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string); } } @@ -229,7 +229,7 @@ void QV8Engine::freezeObject(const QV4::Value &value) QV4::ScopedFunctionObject f(scope, m_freezeObject.value()); QV4::ScopedCallData callData(scope, 1); callData->args[0] = value; - callData->thisObject = m_v4Engine->globalObject(); + callData->thisObject = m_v4Engine->globalObject; f->call(callData); } @@ -266,9 +266,7 @@ void QV8Engine::setExtensionData(int index, Deletable *data) void QV8Engine::initQmlGlobalObject() { initializeGlobal(); - QV4::Scope scope(m_v4Engine); - QV4::ScopedValue v(scope, m_v4Engine->globalObject()); - freezeObject(v); + freezeObject(*m_v4Engine->globalObject); } void QV8Engine::setEngine(QQmlEngine *engine) @@ -279,7 +277,7 @@ void QV8Engine::setEngine(QQmlEngine *engine) QV4::ReturnedValue QV8Engine::global() { - return m_v4Engine->globalObject()->asReturnedValue(); + return m_v4Engine->globalObject->asReturnedValue(); } void QV8Engine::startTimer(const QString &timerName) diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index fb538772d1..94e7d2f140 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -60,7 +60,7 @@ #include <private/qqmlpropertycache_p.h> #include <private/qv4qobjectwrapper_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4object_p.h> #include <private/qv4identifier_p.h> diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 7814fa6d56..43c583ca84 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -277,21 +277,17 @@ void QQmlBind::eval() if (!d->when) { //restore any previous binding if (d->prevBind) { - QQmlAbstractBinding *tmp = d->prevBind; + QQmlAbstractBinding *b = QQmlPropertyPrivate::binding(d->prop); + if (b != d->prevBind) + QQmlPropertyPrivate::setBinding(d->prevBind, QQmlPropertyPrivate::DestroyOldBinding); d->prevBind = 0; - tmp = QQmlPropertyPrivate::setBinding(d->prop, tmp); - if (tmp) //should this ever be true? - tmp->destroy(); } return; } //save any set binding for restoration - QQmlAbstractBinding *tmp; - tmp = QQmlPropertyPrivate::setBinding(d->prop, 0); - if (tmp && d->prevBind) - tmp->destroy(); - else if (!d->prevBind) + QQmlAbstractBinding *tmp = QQmlPropertyPrivate::removeBinding(d->prop, (d->prevBind ? QQmlPropertyPrivate::DestroyOldBinding : QQmlPropertyPrivate::None)); + if (tmp && !d->prevBind) d->prevBind = tmp; } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 201fd4572c..d5fa2f4972 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -44,7 +44,7 @@ #include <private/qqmlincubator_p.h> #include <private/qqmlcompiler_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <qv4objectiterator_p.h> @@ -86,16 +86,11 @@ struct DelegateModelGroupFunction : QV4::FunctionObject return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code); } - static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *) + static QV4::ReturnedValue call(const QV4::Managed *that, QV4::CallData *callData) { - return static_cast<DelegateModelGroupFunction *>(m)->engine()->throwTypeError(); - } - - static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData) - { - QV4::ExecutionEngine *v4 = static_cast<DelegateModelGroupFunction *>(that)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const DelegateModelGroupFunction *>(that)->engine(); QV4::Scope scope(v4); - QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<DelegateModelGroupFunction *>(that)); + QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that)); QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject); if (!o) return v4->throwTypeError(QStringLiteral("Not a valid VisualData object")); @@ -1637,7 +1632,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const if (!object.isObject()) return false; - QV4::ExecutionEngine *v4 = object.asObject()->engine(); + QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine(); QV4::Scope scope(v4); QV4::ScopedObject o(scope, object); if (!o) @@ -2511,7 +2506,7 @@ bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *ind if (!value.isObject()) return false; - QV4::ExecutionEngine *v4 = value.asObject()->engine(); + QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine(); QV4::Scope scope(v4); QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value); @@ -2579,9 +2574,9 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args) groups |= model->m_cacheMetaType->parseGroups(val); } - if (v->asArrayObject()) { + if (v->as<QV4::ArrayObject>()) { return; - } else if (v->asObject()) { + } else if (v->as<QV4::Object>()) { model->insert(before, v, groups); model->emitChanges(); } @@ -2626,7 +2621,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args) if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) { v = (*args)[i]; - if (v->asObject()) { + if (v->as<QV4::Object>()) { int groups = 1 << d->group; if (++i < args->length()) { QV4::ScopedValue val(scope, (*args)[i]); @@ -3286,12 +3281,12 @@ public: quint32 count() const { return d()->changes.count(); } const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); } - static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty) + static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) { Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>()); - QV4::ExecutionEngine *v4 = static_cast<QQmlDelegateModelGroupChangeArray *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine(); QV4::Scope scope(v4); - QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<QQmlDelegateModelGroupChangeArray *>(m)); + QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m)); if (index >= array->count()) { if (hasProperty) @@ -3311,10 +3306,10 @@ public: return object.asReturnedValue(); } - static QV4::ReturnedValue get(QV4::Managed *m, QV4::String *name, bool *hasProperty) + static QV4::ReturnedValue get(const QV4::Managed *m, QV4::String *name, bool *hasProperty) { Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>()); - QQmlDelegateModelGroupChangeArray *array = static_cast<QQmlDelegateModelGroupChangeArray *>(m); + const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m); if (name->equals(array->engine()->id_length)) { if (hasProperty) diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index ed97690adb..b376ce7fcb 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -421,13 +421,13 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) int roleIndex = -1; // Add the value now - if (QV4::String *s = propertyValue->asString()) { + if (const QV4::String *s = propertyValue->as<QV4::String>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String); roleIndex = e->setStringProperty(r, s->toQString()); } else if (propertyValue->isNumber()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number); roleIndex = e->setDoubleProperty(r, propertyValue->asDouble()); - } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) { + } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List); ListModel *subModel = new ListModel(r.subLayout, 0, -1); @@ -441,11 +441,11 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) } else if (propertyValue->isBoolean()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool); roleIndex = e->setBoolProperty(r, propertyValue->booleanValue()); - } else if (QV4::DateObject *dd = propertyValue->asDateObject()) { + } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime); QDateTime dt = dd->toQDateTime(); roleIndex = e->setDateTimeProperty(r, dt); - } else if (QV4::Object *o = propertyValue->asObject()) { + } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) { if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) { QObject *o = wrapper->object(); const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject); @@ -502,7 +502,7 @@ void ListModel::set(int elementIndex, QV4::Object *object) if (r.type == ListLayout::Role::Number) { e->setDoublePropertyFast(r, propertyValue->asDouble()); } - } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) { + } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List); if (r.type == ListLayout::Role::List) { ListModel *subModel = new ListModel(r.subLayout, 0, -1); @@ -520,13 +520,13 @@ void ListModel::set(int elementIndex, QV4::Object *object) if (r.type == ListLayout::Role::Bool) { e->setBoolPropertyFast(r, propertyValue->booleanValue()); } - } else if (QV4::DateObject *date = propertyValue->asDateObject()) { + } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime); if (r.type == ListLayout::Role::DateTime) { QDateTime dt = date->toQDateTime();; e->setDateTimePropertyFast(r, dt); } - } else if (QV4::Object *o = propertyValue->asObject()) { + } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) { if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) { QObject *o = wrapper->object(); const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject); @@ -1169,7 +1169,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d roleIndex = setStringProperty(role, qstr); } else if (d.isNumber()) { roleIndex = setDoubleProperty(role, d.asDouble()); - } else if (d.asArrayObject()) { + } else if (d.as<QV4::ArrayObject>()) { QV4::ScopedArrayObject a(scope, d); if (role.type == ListLayout::Role::List) { QV4::Scope scope(a->engine()); @@ -1187,7 +1187,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d } } else if (d.isBoolean()) { roleIndex = setBoolProperty(role, d.booleanValue()); - } else if (d.asDateObject()) { + } else if (d.as<QV4::DateObject>()) { QV4::Scoped<QV4::DateObject> dd(scope, d); QDateTime dt = dd->toQDateTime(); roleIndex = setDateTimeProperty(role, dt); @@ -1330,8 +1330,8 @@ void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int> QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner); QVariantList subArray = value.toList(); - QVariantList::const_iterator subIt = subArray.begin(); - QVariantList::const_iterator subEnd = subArray.end(); + QVariantList::const_iterator subIt = subArray.cbegin(); + QVariantList::const_iterator subEnd = subArray.cend(); while (subIt != subEnd) { const QVariantMap &subObject = subIt->toMap(); subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel)); @@ -1398,8 +1398,8 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index) QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel); QVariantList subArray = v.toList(); - QVariantList::const_iterator subIt = subArray.begin(); - QVariantList::const_iterator subEnd = subArray.end(); + QVariantList::const_iterator subIt = subArray.cbegin(); + QVariantList::const_iterator subEnd = subArray.cend(); while (subIt != subEnd) { const QVariantMap &subObject = subIt->toMap(); subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel)); diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index c2c6e5ef5c..0aa5dc4ef6 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -54,7 +54,7 @@ #include <private/qv8engine_p.h> #include <private/qv4serialize_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4script_p.h> #include <private/qv4scopedvalue_p.h> diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 356970eef0..e043d4e2ee 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -38,7 +38,7 @@ #include <private/qqmlproperty_p.h> #include <private/qv8engine_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro index df1b750282..85f21ce6f6 100644 --- a/src/qmldevtools/qmldevtools.pro +++ b/src/qmldevtools/qmldevtools.pro @@ -19,3 +19,4 @@ include(../3rdparty/masm/masm-defs.pri) include(../qml/parser/parser.pri) include(../qml/jsruntime/jsruntime.pri) include(../qml/compiler/compiler.pri) +include(../qml/memory/memory.pri) diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp index 3f91ce85a8..e405a53936 100644 --- a/src/qmltest/quicktestresult.cpp +++ b/src/qmltest/quicktestresult.cpp @@ -108,6 +108,14 @@ public Q_SLOTS: pixel += x; return QColor::fromRgba(*pixel); } + + bool equals(QuickTestImageObject *other) const + { + if (!other) + return m_image.isNull(); + + return m_image == other->m_image; + } private: QImage m_image; }; @@ -478,8 +486,8 @@ void QuickTestResult::stringify(QQmlV4Function *args) //Check for Object Type if (value->isObject() - && !value->asFunctionObject() - && !value->asArrayObject()) { + && !value->as<QV4::FunctionObject>() + && !value->as<QV4::ArrayObject>()) { QVariant v = scope.engine->toVariant(value, QMetaType::UnknownType); if (v.isValid()) { switch (v.type()) { @@ -500,7 +508,7 @@ void QuickTestResult::stringify(QQmlV4Function *args) if (result.isEmpty()) { QString tmp = value->toQStringNoThrow(); - if (value->asArrayObject()) + if (value->as<QV4::ArrayObject>()) result.append(QString::fromLatin1("[%1]").arg(tmp)); else result.append(tmp); diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index cb694c499a..2068809b4e 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -46,7 +46,7 @@ #include <QtCore/QBuffer> #include <QtCore/qdatetime.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4scopedvalue_p.h> diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 4aa3b1c8d0..85c45609b5 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -53,7 +53,7 @@ #include <private/qv4object_p.h> #include <private/qquickwindow_p.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4objectproto_p.h> #include <private/qv4scopedvalue_p.h> @@ -884,7 +884,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object V4_OBJECT2(QQuickJSContext2DPixelData, QV4::Object) V4_NEEDS_DESTROY - static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty); + static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty); static void putIndexed(QV4::Managed *m, uint index, const QV4::Value &value); static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx); @@ -1379,7 +1379,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx QV4::ScopedValue value(scope, ctx->argument(0)); - if (value->asObject()) { + if (value->as<Object>()) { QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>(); if (color.isValid()) { r->d()->context->state.fillStyle = color; @@ -1488,7 +1488,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c QV4::ScopedValue value(scope, ctx->argument(0)); - if (value->asObject()) { + if (value->as<Object>()) { QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>(); if (color.isValid()) { r->d()->context->state.fillStyle = color; @@ -1719,7 +1719,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon } else { QImage patternTexture; - if (QV4::Object *o = ctx->args()[0].asObject()) { + if (const QV4::Object *o = ctx->args()[0].as<Object>()) { QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data"))); QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s)); if (!!pixelData) { @@ -3089,12 +3089,12 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext return QV4::Encode(r->d()->image.width() * r->d()->image.height() * 4); } -QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint index, bool *hasProperty) +QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) { Q_ASSERT(m->as<QQuickJSContext2DPixelData>()); - QV4::ExecutionEngine *v4 = static_cast<QQuickJSContext2DPixelData *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QQuickJSContext2DPixelData *>(m)->engine(); QV4::Scope scope(v4); - QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m)); + QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<const QQuickJSContext2DPixelData *>(m)); if (index < static_cast<quint32>(r->d()->image.width() * r->d()->image.height() * 4)) { if (hasProperty) @@ -3357,7 +3357,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo qreal pos = ctx->args()[0].toNumber(); QColor color; - if (ctx->args()[1].asObject()) { + if (ctx->args()[1].as<Object>()) { color = scope.engine->toVariant(ctx->args()[1], qMetaTypeId<QColor>()).value<QColor>(); } else { color = qt_color_from_string(ctx->args()[1]); diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h index 67d3a2e4fb..78fa26d791 100644 --- a/src/quick/items/context2d/qquickcontext2d_p.h +++ b/src/quick/items/context2d/qquickcontext2d_p.h @@ -48,7 +48,7 @@ #include <private/qv8engine_p.h> #include <QtCore/QWaitCondition> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> //#define QQUICKCONTEXT2D_DEBUG //enable this for just DEBUG purpose! diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h index 5b1aea5940..443d796c44 100644 --- a/src/quick/items/qquickimage_p.h +++ b/src/quick/items/qquickimage_p.h @@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE class QQuickImagePrivate; -class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase +class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase { Q_OBJECT Q_ENUMS(FillMode) diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 8b4723f340..6e50a9a77b 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -158,11 +158,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickPathView>(uri,major,minor,"PathView"); qmlRegisterUncreatableType<QQuickBasePositioner>(uri,major,minor,"Positioner", QStringLiteral("Positioner is an abstract type that is only available as an attached property.")); -#ifndef QT_NO_VALIDATOR - qmlRegisterType<QQuickIntValidator>(uri,major,minor,"IntValidator"); - qmlRegisterType<QQuickDoubleValidator>(uri,major,minor,"DoubleValidator"); - qmlRegisterType<QRegExpValidator>(uri,major,minor,"RegExpValidator"); -#endif qmlRegisterType<QQuickRectangle>(uri,major,minor,"Rectangle"); qmlRegisterType<QQuickRepeater>(uri,major,minor,"Repeater"); qmlRegisterType<QQuickRow>(uri,major,minor,"Row"); @@ -190,9 +185,6 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickCurve>(); qmlRegisterType<QQuickScaleGrid>(); qmlRegisterType<QQuickTextLine>(); -#ifndef QT_NO_VALIDATOR - qmlRegisterType<QValidator>(); -#endif qmlRegisterType<QQuickPen>(); qmlRegisterType<QQuickFlickableVisibleArea>(); qRegisterMetaType<QQuickAnchorLine>("QQuickAnchorLine"); @@ -268,6 +260,16 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickPinchArea, 1>(uri, 2, 5,"PinchArea"); qmlRegisterType<QQuickImage, 2>(uri, 2, 5,"Image"); + + qmlRegisterType<QQuickText, 6>(uri, 2, 6, "Text"); + qmlRegisterType<QQuickTextEdit, 6>(uri, 2, 6, "TextEdit"); + qmlRegisterType<QQuickTextInput, 6>(uri, 2, 6, "TextInput"); + qmlRegisterUncreatableType<QQuickBasePositioner, 6>(uri, 2, 6, "Positioner", + QStringLiteral("Positioner is an abstract type that is only available as an attached property.")); + qmlRegisterType<QQuickColumn, 6>(uri, 2, 6, "Column"); + qmlRegisterType<QQuickRow, 6>(uri, 2, 6, "Row"); + qmlRegisterType<QQuickGrid, 6>(uri, 2, 6, "Grid"); + qmlRegisterType<QQuickFlow, 6>(uri, 2, 6, "Flow"); } static void initResources() diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 01ef1e65f7..20d7eba45a 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -2421,7 +2421,7 @@ void QQuickItemViewPrivate::updateUnrequestedIndexes() void QQuickItemViewPrivate::updateUnrequestedPositions() { - for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.begin(), cend = unrequestedItems.end(); it != cend; ++it) + for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) repositionPackageItemAt(it.key(), it.value()); } diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp index 7fa6cdc161..6fa299bf03 100644 --- a/src/quick/items/qquickitemviewtransition.cpp +++ b/src/quick/items/qquickitemviewtransition.cpp @@ -34,6 +34,7 @@ #include "qquickitemviewtransition_p.h" #include <QtQuick/qquickitem.h> #include <QtQuick/private/qquicktransition_p.h> +#include <QtQuick/private/qquicktransitionmanager_p_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h index 170072a814..6f93697cc5 100644 --- a/src/quick/items/qquickitemviewtransition_p.h +++ b/src/quick/items/qquickitemviewtransition_p.h @@ -34,16 +34,20 @@ #ifndef QQUICKITEMVIEWTRANSITION_P_P_H #define QQUICKITEMVIEWTRANSITION_P_P_H -#include <private/qquicktransitionmanager_p_p.h> +#include <QtQuick/private/qtquickglobal_p.h> +#include <QtCore/qobject.h> +#include <QtCore/qpoint.h> +#include <QtQml/qqml.h> QT_BEGIN_NAMESPACE class QQuickItem; +class QQuickTransition; class QQuickItemViewTransitionableItem; class QQuickItemViewTransitionJob; -class QQuickItemViewTransitionChangeListener +class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionChangeListener { public: QQuickItemViewTransitionChangeListener() {} @@ -53,7 +57,7 @@ public: }; -class QQuickItemViewTransitioner +class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitioner { public: enum TransitionType { @@ -113,7 +117,7 @@ private: /* An item that can be transitioned using QQuickViewTransitionJob. */ -class QQuickItemViewTransitionableItem +class Q_QUICK_PRIVATE_EXPORT QQuickItemViewTransitionableItem { public: QQuickItemViewTransitionableItem(QQuickItem *i); diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 3d28bf08c1..c1e3fbb4e0 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -942,7 +942,7 @@ QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Funct QV4::ScopedValue valuemap(scope, QV4::Primitive::undefinedValue()); if (args->length() >= 2) { QV4::ScopedValue v(scope, (*args)[1]); - if (!v->isObject() || v->asArrayObject()) { + if (!v->isObject() || v->as<QV4::ArrayObject>()) { *error = true; qmlInfo(loader) << QQuickLoader::tr("setSource: value is not an object"); } else { diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h index 621419d1a7..fb1263f0bd 100644 --- a/src/quick/items/qquickloader_p_p.h +++ b/src/quick/items/qquickloader_p_p.h @@ -50,7 +50,7 @@ #include "qquickitemchangelistener_p.h" #include <qqmlincubator.h> -#include <private/qv4value_inl_p.h> +#include <private/qv4value_p.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h index 3712e964f8..2759d9d683 100644 --- a/src/quick/items/qquickpainteditem_p.h +++ b/src/quick/items/qquickpainteditem_p.h @@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE class QQuickPaintedItemTextureProvider; class QSGPainterNode; -class QQuickPaintedItemPrivate : public QQuickItemPrivate +class Q_QUICK_PRIVATE_EXPORT QQuickPaintedItemPrivate : public QQuickItemPrivate { public: QQuickPaintedItemPrivate(); diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 58605f79dd..302532c3d1 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -98,7 +98,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate() , inRefill(false) , dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY) , moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0) - , firstIndex(-1), pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) + , pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0) , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0) , moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition) , highlightPosition(0) @@ -447,7 +447,6 @@ void QQuickPathViewPrivate::regenerate() if (!isValid()) return; - firstIndex = -1; updateMappedRange(); q->refill(); } @@ -1473,7 +1472,7 @@ int QQuickPathView::indexAt(qreal x, qreal y) const QQuickItem *item = d->items.at(idx); QPointF p = item->mapFromItem(this, QPointF(x, y)); if (item->contains(p)) - return (d->firstIndex + idx) % d->modelCount; + return d->model->indexOf(item, 0); } return -1; @@ -1896,12 +1895,12 @@ void QQuickPathView::refill() int count = d->pathItems == -1 ? d->modelCount : qMin(d->pathItems, d->modelCount); // first move existing items and remove items off path - int idx = d->firstIndex; - qCDebug(lcItemViewDelegateLifecycle) << "firstIndex" << idx << "currentIndex" << d->currentIndex << "offset" << d->offset; + qCDebug(lcItemViewDelegateLifecycle) << "currentIndex" << d->currentIndex << "offset" << d->offset; QList<QQuickItem*>::iterator it = d->items.begin(); while (it != d->items.end()) { - qreal pos = d->positionOfIndex(idx); QQuickItem *item = *it; + int idx = d->model->indexOf(item, 0); + qreal pos = d->positionOfIndex(idx); if (lcItemViewDelegateLifecycle().isDebugEnabled()) { QQuickText *text = qmlobject_cast<QQuickText*>(item); if (text) @@ -1923,81 +1922,140 @@ void QQuickPathView::refill() if (!d->isInBound(pos, d->mappedRange - d->mappedCache, 1.0 + d->mappedCache)) { qCDebug(lcItemViewDelegateLifecycle) << "release" << idx << "@" << pos << ", !isInBound: lower" << (d->mappedRange - d->mappedCache) << "upper" << (1.0 + d->mappedCache); d->releaseItem(item); - if (it == d->items.begin()) { - if (++d->firstIndex >= d->modelCount) { - d->firstIndex = 0; - } - } it = d->items.erase(it); } else { ++it; } } - ++idx; - if (idx >= d->modelCount) - idx = 0; } - if (!d->items.count()) - d->firstIndex = -1; - bool waiting = false; if (d->modelCount) { - // add items to beginning and end + // add items as needed if (d->items.count() < count+d->cacheSize) { - int idx = qRound(d->modelCount - d->offset) % d->modelCount; + int endIdx = 0; + qreal endPos; + int startIdx = 0; qreal startPos = 0.0; - if (d->haveHighlightRange && (d->highlightRangeMode != QQuickPathView::NoHighlightRange - || d->snapMode != QQuickPathView::NoSnap)) - startPos = d->highlightRangeStart; - if (d->firstIndex >= 0) { - startPos = d->positionOfIndex(d->firstIndex); - idx = (d->firstIndex + d->items.count()) % d->modelCount; + if (d->items.count()) { + //Find the beginning and end, items may not be in sorted order + endPos = -1.0; + startPos = 2.0; + + for (int i = 0; i < d->items.count(); i++) { + int idx = d->model->indexOf(d->items[i], 0); + qreal curPos = d->positionOfIndex(idx); + if (curPos > endPos) { + endPos = curPos; + endIdx = idx; + } + + if (curPos < startPos) { + startPos = curPos; + startIdx = idx; + } + } + } else { + if (d->haveHighlightRange + && (d->highlightRangeMode != QQuickPathView::NoHighlightRange + || d->snapMode != QQuickPathView::NoSnap)) + startPos = d->highlightRangeStart; + // With no items, then "end" is just off the top so we populate via append + endIdx = (qRound(d->modelCount - d->offset) - 1) % d->modelCount; + endPos = d->positionOfIndex(endIdx); } - qreal pos = d->positionOfIndex(idx); - while ((d->isInBound(pos, startPos, 1.0 + d->mappedCache) || !d->items.count()) && d->items.count() < count+d->cacheSize) { - qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); - QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0); + //Append + int idx = endIdx + 1; + if (idx >= d->modelCount) + idx = 0; + qreal nextPos = d->positionOfIndex(idx); + while ((d->isInBound(nextPos, endPos, 1.0 + d->mappedCache) || !d->items.count()) + && d->items.count() < count+d->cacheSize) { + qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); + QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0); if (!item) { waiting = true; break; } + if (d->items.contains(item)) { + break; //Otherwise we'd "re-add" it, and get confused + } if (d->currentIndex == idx) { currentVisible = true; - d->currentItemOffset = pos; + d->currentItemOffset = nextPos; } - if (d->items.count() == 0) - d->firstIndex = idx; d->items.append(item); - d->updateItem(item, pos); + d->updateItem(item, nextPos); + endIdx = idx; + endPos = nextPos; ++idx; if (idx >= d->modelCount) idx = 0; - pos = d->positionOfIndex(idx); + nextPos = d->positionOfIndex(idx); } - idx = d->firstIndex - 1; + //Prepend + idx = startIdx - 1; if (idx < 0) idx = d->modelCount - 1; - pos = d->positionOfIndex(idx); - while (!waiting && d->isInBound(pos, d->mappedRange - d->mappedCache, startPos) && d->items.count() < count+d->cacheSize) { - qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << pos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); - QQuickItem *item = d->getItem(idx, idx+1, pos >= 1.0); + nextPos = d->positionOfIndex(idx); + while (!waiting && d->isInBound(nextPos, d->mappedRange - d->mappedCache, startPos) + && d->items.count() < count+d->cacheSize) { + qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); + QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0); if (!item) { waiting = true; break; } + if (d->items.contains(item)) { + break; //Otherwise we'd "re-add" it, and get confused + } if (d->currentIndex == idx) { currentVisible = true; - d->currentItemOffset = pos; + d->currentItemOffset = nextPos; } d->items.prepend(item); - d->updateItem(item, pos); - d->firstIndex = idx; - idx = d->firstIndex - 1; + d->updateItem(item, nextPos); + startIdx = idx; + startPos = nextPos; + --idx; if (idx < 0) idx = d->modelCount - 1; - pos = d->positionOfIndex(idx); + nextPos = d->positionOfIndex(idx); + } + + // In rare cases, when jumping around with pathCount close to modelCount, + // new items appear in the middle. This more generic addition iteration handles this + // Since this is the rare case, we try append/prepend first and only do this if + // there are gaps still left to fill. + if (!waiting && d->items.count() < count+d->cacheSize) { + qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.count(); + idx = startIdx; + QQuickItem *lastItem = d->items[0]; + while (idx != endIdx) { + //This gets the reference from the delegate model, and will not re-create + QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0); + if (!item) { + waiting = true; + break; + } + if (!d->items.contains(item)) { //We found a hole + nextPos = d->positionOfIndex(idx); + qCDebug(lcItemViewDelegateLifecycle) << "middle insert" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count(); + if (d->currentIndex == idx) { + currentVisible = true; + d->currentItemOffset = nextPos; + } + int lastListIdx = d->items.indexOf(lastItem); + d->items.insert(lastListIdx + 1, item); + d->updateItem(item, nextPos); + } + + lastItem = item; + ++idx; + if (idx >= d->modelCount) + idx = 0; + } } } } @@ -2128,7 +2186,6 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) d->offset = qmlMod(d->modelCount - d->currentIndex, d->modelCount); changedOffset = true; } - d->firstIndex = -1; d->updateMappedRange(); d->scheduleLayout(); } @@ -2185,8 +2242,16 @@ void QQuickPathViewPrivate::createCurrentItem() { if (requestedIndex != -1) return; - int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount; - if (itemIndex < items.count()) { + + bool inItems = false; + for (int i = 0; i < items.count(); i++) { + if (model->indexOf(items[i], 0) == currentIndex) { + inItems = true; + break; + } + } + + if (inItems) { if ((currentItem = getItem(currentIndex, currentIndex))) { currentItem->setFocus(true); if (QQuickPathViewAttached *att = attached(currentItem)) diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index 35ea8616a5..2a497881d4 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -155,7 +155,6 @@ public: QQuickTimeLine tl; QQuickTimeLineValueProxy<QQuickPathViewPrivate> moveOffset; int flickDuration; - int firstIndex; int pathItems; int requestedIndex; int cacheSize; diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 887d317069..c2eb7a9ac3 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -70,6 +70,10 @@ QQuickBasePositioner::PositionedItem::PositionedItem(QQuickItem *i) , index(-1) , isNew(false) , isVisible(true) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) { } @@ -116,6 +120,14 @@ void QQuickBasePositioner::PositionedItem::startTransition(QQuickItemViewTransit transitionableItem->startTransition(transitioner, index); } +void QQuickBasePositioner::PositionedItem::updatePadding(qreal lp, qreal tp, qreal rp, qreal bp) +{ + leftPadding = lp; + topPadding = tp; + rightPadding = rp; + bottomPadding = bp; +} + QQuickBasePositioner::QQuickBasePositioner(PositionerType at, QQuickItem *parent) : QQuickImplicitSizeItem(*(new QQuickBasePositionerPrivate), parent) @@ -388,11 +400,8 @@ void QQuickBasePositioner::prePositioning() void QQuickBasePositioner::positionItem(qreal x, qreal y, PositionedItem *target) { - Q_D(QQuickBasePositioner); - if ( (target->itemX() != x || target->itemY() != y) - && d->type == Both) { + if ( target->itemX() != x || target->itemY() != y ) target->moveTo(QPointF(x, y)); - } } void QQuickBasePositioner::positionItemX(qreal x, PositionedItem *target) @@ -503,6 +512,163 @@ void QQuickBasePositioner::updateAttachedProperties(QQuickPositionerAttached *sp } } +qreal QQuickBasePositioner::padding() const +{ + Q_D(const QQuickBasePositioner); + return d->padding; +} + +void QQuickBasePositioner::setPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + if (qFuzzyCompare(d->padding, padding)) + return; + d->padding = padding; + d->setPositioningDirty(); + emit paddingChanged(); + if (!d->explicitTopPadding) + emit topPaddingChanged(); + if (!d->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickBasePositioner::resetPadding() +{ + setPadding(0); +} + +qreal QQuickBasePositioner::topPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->explicitTopPadding) + return d->topPadding; + return d->padding; +} + +void QQuickBasePositioner::setTopPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setTopPadding(padding); +} + +void QQuickBasePositioner::resetTopPadding() +{ + Q_D(QQuickBasePositioner); + d->setTopPadding(0, true); +} + +qreal QQuickBasePositioner::leftPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->explicitLeftPadding) + return d->leftPadding; + return d->padding; +} + +void QQuickBasePositioner::setLeftPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setLeftPadding(padding); +} + +void QQuickBasePositioner::resetLeftPadding() +{ + Q_D(QQuickBasePositioner); + d->setLeftPadding(0, true); +} + +qreal QQuickBasePositioner::rightPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->explicitRightPadding) + return d->rightPadding; + return d->padding; +} + +void QQuickBasePositioner::setRightPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setRightPadding(padding); +} + +void QQuickBasePositioner::resetRightPadding() +{ + Q_D(QQuickBasePositioner); + d->setRightPadding(0, true); +} + +qreal QQuickBasePositioner::bottomPadding() const +{ + Q_D(const QQuickBasePositioner); + if (d->explicitBottomPadding) + return d->bottomPadding; + return d->padding; +} + +void QQuickBasePositioner::setBottomPadding(qreal padding) +{ + Q_D(QQuickBasePositioner); + d->setBottomPadding(padding); +} + +void QQuickBasePositioner::resetBottomPadding() +{ + Q_D(QQuickBasePositioner); + d->setBottomPadding(0, true); +} + +void QQuickBasePositionerPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal tmp = q->topPadding(); + topPadding = value; + explicitTopPadding = !reset; + if ((!reset && !qFuzzyCompare(tmp, value)) || (reset && !qFuzzyCompare(tmp, padding))) { + setPositioningDirty(); + emit q->topPaddingChanged(); + } +} + +void QQuickBasePositionerPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal tmp = q->leftPadding(); + leftPadding = value; + explicitLeftPadding = !reset; + if ((!reset && !qFuzzyCompare(tmp, value)) || (reset && !qFuzzyCompare(tmp, padding))) { + setPositioningDirty(); + emit q->leftPaddingChanged(); + } +} + +void QQuickBasePositionerPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal tmp = q->rightPadding(); + rightPadding = value; + explicitRightPadding = !reset; + if ((!reset && !qFuzzyCompare(tmp, value)) || (reset && !qFuzzyCompare(tmp, padding))) { + setPositioningDirty(); + emit q->rightPaddingChanged(); + } +} + +void QQuickBasePositionerPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickBasePositioner); + qreal tmp = q->bottomPadding(); + bottomPadding = value; + explicitBottomPadding = !reset; + if ((!reset && !qFuzzyCompare(tmp, value)) || (reset && !qFuzzyCompare(tmp, padding))) { + setPositioningDirty(); + emit q->bottomPaddingChanged(); + } +} + /*! \qmltype Positioner \instantiates QQuickPositionerAttached @@ -640,6 +806,16 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem) \sa Row, Grid, Flow, Positioner, ColumnLayout, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Column::padding + \qmlproperty real QtQuick::Column::topPadding + \qmlproperty real QtQuick::Column::leftPadding + \qmlproperty real QtQuick::Column::bottomPadding + \qmlproperty real QtQuick::Column::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Column::populate This property holds the transition to be run for items that are part of @@ -715,20 +891,23 @@ QQuickColumn::QQuickColumn(QQuickItem *parent) void QQuickColumn::doPositioning(QSizeF *contentSize) { //Precondition: All items in the positioned list have a valid item pointer and should be positioned - qreal voffset = 0; + qreal voffset = topPadding(); + const qreal padding = leftPadding() + rightPadding(); + contentSize->setWidth(qMax(contentSize->width(), padding)); for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; - positionItemY(voffset, &child); - contentSize->setWidth(qMax(contentSize->width(), child.item->width())); + positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); + contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding)); voffset += child.item->height(); voffset += spacing(); } - if (voffset != 0)//If we positioned any items, undo the spacing from the last item + if (voffset - topPadding() != 0)//If we positioned any items, undo the spacing from the last item voffset -= spacing(); - contentSize->setHeight(voffset); + contentSize->setHeight(voffset + bottomPadding()); } void QQuickColumn::reportConflictingAnchors() @@ -794,6 +973,16 @@ void QQuickColumn::reportConflictingAnchors() \sa Column, Grid, Flow, Positioner, RowLayout, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Row::padding + \qmlproperty real QtQuick::Row::topPadding + \qmlproperty real QtQuick::Row::leftPadding + \qmlproperty real QtQuick::Row::bottomPadding + \qmlproperty real QtQuick::Row::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Row::populate This property holds the transition to be run for items that are part of @@ -940,27 +1129,34 @@ void QQuickRow::doPositioning(QSizeF *contentSize) { //Precondition: All items in the positioned list have a valid item pointer and should be positioned QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate* >(QQuickBasePositionerPrivate::get(this)); - qreal hoffset = 0; + qreal hoffset1 = leftPadding(); + qreal hoffset2 = rightPadding(); + if (!d->isLeftToRight()) + qSwap(hoffset1, hoffset2); + qreal hoffset = hoffset1; + const qreal padding = topPadding() + bottomPadding(); + contentSize->setHeight(qMax(contentSize->height(), padding)); QList<qreal> hoffsets; for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; if (d->isLeftToRight()) { - positionItemX(hoffset, &child); + positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } else { hoffsets << hoffset; } - contentSize->setHeight(qMax(contentSize->height(), child.item->height())); + contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding)); hoffset += child.item->width(); hoffset += spacing(); } - if (hoffset != 0)//If we positioned any items, undo the extra spacing from the last item + if (hoffset - hoffset1 != 0)//If we positioned any items, undo the extra spacing from the last item hoffset -= spacing(); - contentSize->setWidth(hoffset); + contentSize->setWidth(hoffset + hoffset2); if (d->isLeftToRight()) return; @@ -976,7 +1172,8 @@ void QQuickRow::doPositioning(QSizeF *contentSize) for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; hoffset = end - hoffsets[acc++] - child.item->width(); - positionItemX(hoffset, &child); + positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } } @@ -1044,6 +1241,16 @@ void QQuickRow::reportConflictingAnchors() \sa Flow, Row, Column, Positioner, GridLayout, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Grid::padding + \qmlproperty real QtQuick::Grid::topPadding + \qmlproperty real QtQuick::Grid::leftPadding + \qmlproperty real QtQuick::Grid::bottomPadding + \qmlproperty real QtQuick::Grid::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Grid::populate This property holds the transition to be run for items that are part of @@ -1423,8 +1630,11 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) c = (numVisible+(m_rows-1))/m_rows; } - if (r == 0 || c == 0) - return; //Nothing to do + if (r == 0 || c == 0) { + contentSize->setHeight(topPadding() + bottomPadding()); + contentSize->setWidth(leftPadding() + rightPadding()); + return; //Nothing else to do + } QList<qreal> maxColWidth; QList<qreal> maxRowHeight; @@ -1476,6 +1686,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) widthSum += columnSpacing; widthSum += maxColWidth[j]; } + widthSum += leftPadding() + rightPadding(); qreal heightSum = 0; for (int i = 0; i < maxRowHeight.size(); i++) { @@ -1483,6 +1694,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) heightSum += rowSpacing; heightSum += maxRowHeight[i]; } + heightSum += topPadding() + bottomPadding(); contentSize->setHeight(heightSum); contentSize->setWidth(widthSum); @@ -1493,10 +1705,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) else end = widthSum; - qreal xoffset = 0; + qreal xoffset = leftPadding(); if (!d->isLeftToRight()) - xoffset = end; - qreal yoffset = 0; + xoffset = end - rightPadding(); + qreal yoffset = topPadding(); int curRow =0; int curCol =0; for (int i = 0; i < positionedItems.count(); ++i) { @@ -1518,6 +1730,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) alignYOffset += maxRowHeight[curRow] - child.item->height(); positionItem(childXOffset, alignYOffset, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); if (m_flow == LeftToRight) { if (d->isLeftToRight()) @@ -1529,9 +1742,9 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) if (!curCol) { yoffset += maxRowHeight[curRow]+rowSpacing; if (d->isLeftToRight()) - xoffset = 0; + xoffset = leftPadding(); else - xoffset = end; + xoffset = end - rightPadding(); curRow++; if (curRow>=r) break; @@ -1545,7 +1758,7 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) xoffset += maxColWidth[curCol]+columnSpacing; else xoffset -= maxColWidth[curCol]+columnSpacing; - yoffset = 0; + yoffset = topPadding(); curCol++; if (curCol>=c) break; @@ -1603,6 +1816,16 @@ void QQuickGrid::reportConflictingAnchors() \sa Column, Row, Grid, Positioner, {Qt Quick Examples - Positioners} */ /*! + \since 5.6 + \qmlproperty real QtQuick::Flow::padding + \qmlproperty real QtQuick::Flow::topPadding + \qmlproperty real QtQuick::Flow::leftPadding + \qmlproperty real QtQuick::Flow::bottomPadding + \qmlproperty real QtQuick::Flow::rightPadding + + These properties hold the padding around the content. +*/ +/*! \qmlproperty Transition QtQuick::Flow::populate This property holds the transition to be run for items that are part of @@ -1786,23 +2009,30 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) //Precondition: All items in the positioned list have a valid item pointer and should be positioned Q_D(QQuickFlow); - qreal hoffset = 0; - qreal voffset = 0; + qreal hoffset1 = leftPadding(); + qreal hoffset2 = rightPadding(); + if (!d->isLeftToRight()) + qSwap(hoffset1, hoffset2); + qreal hoffset = hoffset1; + const qreal voffset1 = topPadding(); + qreal voffset = voffset1; qreal linemax = 0; QList<qreal> hoffsets; + contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2)); + contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding())); for (int i = 0; i < positionedItems.count(); ++i) { PositionedItem &child = positionedItems[i]; if (d->flow == LeftToRight) { - if (widthValid() && hoffset && hoffset + child.item->width() > width()) { - hoffset = 0; + if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) { + hoffset = hoffset1; voffset += linemax + spacing(); linemax = 0; } } else { - if (heightValid() && voffset && voffset + child.item->height() > height()) { - voffset = 0; + if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) { + voffset = voffset1; hoffset += linemax + spacing(); linemax = 0; } @@ -1810,13 +2040,16 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) if (d->isLeftToRight()) { positionItem(hoffset, voffset, &child); + child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } else { hoffsets << hoffset; positionItemY(voffset, &child); + child.topPadding = topPadding(); + child.bottomPadding = bottomPadding(); } - contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width())); - contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height())); + contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2)); + contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding())); if (d->flow == LeftToRight) { hoffset += child.item->width(); @@ -1828,6 +2061,7 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) linemax = qMax(linemax, child.item->width()); } } + if (d->isLeftToRight()) return; @@ -1841,6 +2075,8 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) PositionedItem &child = positionedItems[i]; hoffset = end - hoffsets[acc++] - child.item->width(); positionItemX(hoffset, &child); + child.leftPadding = leftPadding(); + child.rightPadding = rightPadding(); } } diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index ea779695eb..6323405022 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -86,6 +86,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBasePositioner : public QQuickImplicitSizeIte Q_PROPERTY(QQuickTransition *populate READ populate WRITE setPopulate NOTIFY populateChanged) Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged) Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged) + + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) public: enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 }; @@ -108,6 +114,26 @@ public: void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + protected: QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent); void componentComplete() Q_DECL_OVERRIDE; @@ -120,6 +146,11 @@ Q_SIGNALS: void populateChanged(); void moveChanged(); void addChanged(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); protected Q_SLOTS: void prePositioning(); @@ -144,11 +175,18 @@ protected: bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds); void startTransition(QQuickItemViewTransitioner *transitioner); + void updatePadding(qreal lp, qreal tp, qreal rp, qreal bp); + QQuickItem *item; QQuickItemViewTransitionableItem *transitionableItem; int index; bool isNew; bool isVisible; + + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; }; QPODVector<PositionedItem,8> positionedItems; diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h index 3a8fe20351..a58f79ac0a 100644 --- a/src/quick/items/qquickpositioners_p_p.h +++ b/src/quick/items/qquickpositioners_p_p.h @@ -69,6 +69,16 @@ public: : spacing(0), type(QQuickBasePositioner::None) , transitioner(0), positioningDirty(false) , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight) + , padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) + { } @@ -98,6 +108,16 @@ public: Qt::LayoutDirection layoutDirection; + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding; + bool explicitLeftPadding; + bool explicitRightPadding; + bool explicitBottomPadding; + void mirrorChange() Q_DECL_OVERRIDE { effectiveLayoutDirectionChange(); } @@ -149,6 +169,11 @@ public: virtual void effectiveLayoutDirectionChange() { } + + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index 0168d73c8f..5333ad2f08 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -50,6 +50,7 @@ QQuickRepeaterPrivate::QQuickRepeaterPrivate() , delegateValidated(false) , itemCount(0) { + setTransparentForPositioner(true); } QQuickRepeaterPrivate::~QQuickRepeaterPrivate() @@ -397,9 +398,17 @@ void QQuickRepeaterPrivate::requestItems() void QQuickRepeater::createdItem(int index, QObject *) { Q_D(QQuickRepeater); + QObject *object = d->model->object(index, false); + QQuickItem *item = qmlobject_cast<QQuickItem*>(object); + emit itemAdded(index, item); +} + +void QQuickRepeater::initItem(int index, QObject *object) +{ + Q_D(QQuickRepeater); + QQuickItem *item = qmlobject_cast<QQuickItem*>(object); + if (!d->deletables.at(index)) { - QObject *object = d->model->object(index, false); - QQuickItem *item = qmlobject_cast<QQuickItem*>(object); if (!item) { if (object) { d->model->release(object); @@ -425,17 +434,9 @@ void QQuickRepeater::createdItem(int index, QObject *) } item->stackBefore(after); } - emit itemAdded(index, item); } } -void QQuickRepeater::initItem(int, QObject *object) -{ - QQuickItem *item = qmlobject_cast<QQuickItem*>(object); - if (item) - item->setParentItem(parentItem()); -} - void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset) { Q_D(QQuickRepeater); diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index 579919db27..3ea1c0ecf1 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -1024,48 +1024,48 @@ void QQuickAnchorChanges::execute(Reason reason) //reset any anchors that have been specified as "undefined" if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) { targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftProp, 0); + QQmlPropertyPrivate::removeBinding(d->leftProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) { targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightProp, 0); + QQmlPropertyPrivate::removeBinding(d->rightProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) { targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->hCenterProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) { targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topProp, 0); + QQmlPropertyPrivate::removeBinding(d->topProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) { targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomProp, 0); + QQmlPropertyPrivate::removeBinding(d->bottomProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) { targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->vCenterProp); } if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) { targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineProp, 0); + QQmlPropertyPrivate::removeBinding(d->baselineProp); } //set any anchors that have been specified if (d->leftBinding) - QQmlPropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding); + QQmlPropertyPrivate::setBinding(d->leftBinding); if (d->rightBinding) - QQmlPropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding); + QQmlPropertyPrivate::setBinding(d->rightBinding); if (d->hCenterBinding) - QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding); + QQmlPropertyPrivate::setBinding(d->hCenterBinding); if (d->topBinding) - QQmlPropertyPrivate::setBinding(d->topBinding->property(), d->topBinding); + QQmlPropertyPrivate::setBinding(d->topBinding); if (d->bottomBinding) - QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding); + QQmlPropertyPrivate::setBinding(d->bottomBinding); if (d->vCenterBinding) - QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding); + QQmlPropertyPrivate::setBinding(d->vCenterBinding); if (d->baselineBinding) - QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding); + QQmlPropertyPrivate::setBinding(d->baselineBinding); } bool QQuickAnchorChanges::isReversable() @@ -1083,49 +1083,49 @@ void QQuickAnchorChanges::reverse(Reason reason) //reset any anchors set by the state if (d->leftBinding) { targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->leftBinding); if (reason == ActualChange) { d->leftBinding->destroy(); d->leftBinding = 0; } } if (d->rightBinding) { targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->rightBinding); if (reason == ActualChange) { d->rightBinding->destroy(); d->rightBinding = 0; } } if (d->hCenterBinding) { targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->hCenterBinding); if (reason == ActualChange) { d->hCenterBinding->destroy(); d->hCenterBinding = 0; } } if (d->topBinding) { targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->topBinding); if (reason == ActualChange) { d->topBinding->destroy(); d->topBinding = 0; } } if (d->bottomBinding) { targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->bottomBinding); if (reason == ActualChange) { d->bottomBinding->destroy(); d->bottomBinding = 0; } } if (d->vCenterBinding) { targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->vCenterBinding); if (reason == ActualChange) { d->vCenterBinding->destroy(); d->vCenterBinding = 0; } } if (d->baselineBinding) { targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), 0); + QQmlPropertyPrivate::removeBinding(d->baselineBinding); if (reason == ActualChange) { d->baselineBinding->destroy(); d->baselineBinding = 0; } @@ -1333,31 +1333,31 @@ void QQuickAnchorChanges::clearBindings() d->anchorSet->d_func()->usedAnchors; if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) { targetPrivate->anchors()->resetLeft(); - QQmlPropertyPrivate::setBinding(d->leftProp, 0); + QQmlPropertyPrivate::removeBinding(d->leftProp); } if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) { targetPrivate->anchors()->resetRight(); - QQmlPropertyPrivate::setBinding(d->rightProp, 0); + QQmlPropertyPrivate::removeBinding(d->rightProp); } if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) { targetPrivate->anchors()->resetHorizontalCenter(); - QQmlPropertyPrivate::setBinding(d->hCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->hCenterProp); } if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) { targetPrivate->anchors()->resetTop(); - QQmlPropertyPrivate::setBinding(d->topProp, 0); + QQmlPropertyPrivate::removeBinding(d->topProp); } if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) { targetPrivate->anchors()->resetBottom(); - QQmlPropertyPrivate::setBinding(d->bottomProp, 0); + QQmlPropertyPrivate::removeBinding(d->bottomProp); } if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) { targetPrivate->anchors()->resetVerticalCenter(); - QQmlPropertyPrivate::setBinding(d->vCenterProp, 0); + QQmlPropertyPrivate::removeBinding(d->vCenterProp); } if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) { targetPrivate->anchors()->resetBaseline(); - QQmlPropertyPrivate::setBinding(d->baselineProp, 0); + QQmlPropertyPrivate::removeBinding(d->baselineProp); } } diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index dd4f57bfdb..799b1465ea 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE const QChar QQuickTextPrivate::elideChar = QChar(0x2026); QQuickTextPrivate::QQuickTextPrivate() - : elideLayout(0), textLine(0), lineWidth(0) + : elideLayout(0), textLine(0), padding(0), lineWidth(0) , color(0xFF000000), linkColor(0xFF0000FF), styleColor(0xFF000000) , lineCount(1), multilengthEos(-1) , elideMode(QQuickText::ElideNone), hAlign(QQuickText::AlignLeft), vAlign(QQuickText::AlignTop) @@ -85,7 +85,15 @@ QQuickTextPrivate::QQuickTextPrivate() } QQuickTextPrivate::ExtraData::ExtraData() - : lineHeight(1.0) + : topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) + , lineHeight(1.0) , doc(0) , minimumPixelSize(12) , minimumPointSize(12) @@ -283,6 +291,74 @@ qreal QQuickTextPrivate::getImplicitHeight() const return implicitHeight; } +qreal QQuickTextPrivate::availableWidth() const +{ + Q_Q(const QQuickText); + return q->width() - q->leftPadding() - q->rightPadding(); +} + +qreal QQuickTextPrivate::availableHeight() const +{ + Q_Q(const QQuickText); + return q->height() - q->topPadding() - q->bottomPadding(); +} + +void QQuickTextPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->topPadding(); + if (!reset || extra.isAllocated()) { + extra.value().topPadding = value; + extra.value().explicitTopPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateSize(); + emit q->topPaddingChanged(); + } +} + +void QQuickTextPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->leftPadding(); + if (!reset || extra.isAllocated()) { + extra.value().leftPadding = value; + extra.value().explicitLeftPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateSize(); + emit q->leftPaddingChanged(); + } +} + +void QQuickTextPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->rightPadding(); + if (!reset || extra.isAllocated()) { + extra.value().rightPadding = value; + extra.value().explicitRightPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateSize(); + emit q->rightPaddingChanged(); + } +} + +void QQuickTextPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickText); + qreal oldPadding = q->bottomPadding(); + if (!reset || extra.isAllocated()) { + extra.value().bottomPadding = value; + extra.value().explicitBottomPadding = !reset; + } + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateSize(); + emit q->bottomPaddingChanged(); + } +} + /*! \qmlproperty bool QtQuick::Text::antialiasing @@ -409,7 +485,7 @@ void QQuickTextPrivate::updateBaseline(qreal baseline, qreal dy) yoff = dy/2; } - q->setBaselineOffset(baseline + yoff); + q->setBaselineOffset(baseline + yoff + q->topPadding()); } void QQuickTextPrivate::updateSize() @@ -429,6 +505,9 @@ void QQuickTextPrivate::updateSize() return; } + qreal hPadding = q->leftPadding() + q->rightPadding(); + qreal vPadding = q->topPadding() + q->bottomPadding(); + if (text.isEmpty() && !isLineLaidOutConnected() && fontSizeMode() == QQuickText::FixedSize) { // How much more expensive is it to just do a full layout on an empty string here? // There may be subtle differences in the height and baseline calculations between @@ -441,8 +520,8 @@ void QQuickTextPrivate::updateSize() ? lineHeight() : fontHeight * lineHeight(); } - updateBaseline(fm.ascent(), q->height() - fontHeight); - q->setImplicitSize(0, fontHeight); + updateBaseline(fm.ascent(), q->height() - fontHeight - vPadding); + q->setImplicitSize(hPadding, fontHeight + vPadding); layedOutTextRect = QRectF(0, 0, 0, fontHeight); emit q->contentSizeChanged(); updateType = UpdatePaintNode; @@ -463,7 +542,7 @@ void QQuickTextPrivate::updateSize() layedOutTextRect = textRect; size = textRect.size(); - updateBaseline(baseline, q->height() - size.height()); + updateBaseline(baseline, q->height() - size.height() - vPadding); } else { widthExceeded = true; // always relayout rich text on width changes.. heightExceeded = false; // rich text layout isn't affected by height changes. @@ -487,15 +566,15 @@ void QQuickTextPrivate::updateSize() naturalWidth = extra->doc->idealWidth(); const bool wasInLayout = internalWidthUpdate; internalWidthUpdate = true; - q->setImplicitWidth(naturalWidth); + q->setImplicitWidth(naturalWidth + hPadding); internalWidthUpdate = wasInLayout; } if (internalWidthUpdate) return; extra->doc->setPageSize(QSizeF()); - if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < q->width())) - extra->doc->setTextWidth(q->width()); + if (q->widthValid() && (wrapMode != QQuickText::NoWrap || extra->doc->idealWidth() < availableWidth())) + extra->doc->setTextWidth(availableWidth()); else extra->doc->setTextWidth(extra->doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) @@ -504,7 +583,7 @@ void QQuickTextPrivate::updateSize() size = QSizeF(extra->doc->idealWidth(),dsize.height()); QFontMetricsF fm(font); - updateBaseline(fm.ascent(), q->height() - size.height()); + updateBaseline(fm.ascent(), q->height() - size.height() - vPadding); //### need to confirm cost of always setting these for richText internalWidthUpdate = true; @@ -512,11 +591,11 @@ void QQuickTextPrivate::updateSize() if (!q->widthValid()) iWidth = size.width(); if (iWidth > -1) - q->setImplicitSize(iWidth, size.height()); + q->setImplicitSize(iWidth + hPadding, size.height() + vPadding); internalWidthUpdate = false; if (iWidth == -1) - q->setImplicitHeight(size.height()); + q->setImplicitHeight(size.height() + vPadding); } if (layedOutTextRect.size() != previousSize) @@ -622,7 +701,7 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, // use the text item's width by default if it has one and wrap is on or text must be aligned if (q->widthValid() && (q->wrapMode() != QQuickText::NoWrap || q->effectiveHAlign() != QQuickText::AlignLeft)) - textLine->setWidth(q->width()); + textLine->setWidth(availableWidth()); else textLine->setWidth(INT_MAX); if (lineHeight() != 1.0) @@ -690,10 +769,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) && (q->heightValid() || maximumLineCountValid); if ((!requireImplicitSize || (implicitWidthValid && implicitHeightValid)) - && ((singlelineElide && q->width() <= 0.) || (multilineElide && q->heightValid() && q->height() <= 0.))) { + && ((singlelineElide && availableWidth() <= 0.) + || (multilineElide && q->heightValid() && availableHeight() <= 0.))) { // we are elided and we have a zero width or height - widthExceeded = q->widthValid() && q->width() <= 0.; - heightExceeded = q->heightValid() && q->height() <= 0.; + widthExceeded = q->widthValid() && availableWidth() <= 0.; + heightExceeded = q->heightValid() && availableHeight() <= 0.; if (!truncated) { truncated = true; @@ -729,7 +809,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) lineWidth = (q->widthValid() || implicitWidthValid) && q->width() > 0 ? q->width() : FLT_MAX; - qreal maxHeight = q->heightValid() ? q->height() : FLT_MAX; + qreal maxHeight = q->heightValid() ? availableHeight() : FLT_MAX; const bool customLayout = isLineLaidOutConnected(); const bool wasTruncated = truncated; @@ -750,8 +830,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) int scaledFontSize = largeFont; bool widthChanged = false; - widthExceeded = q->width() <= 0 && (singlelineElide || canWrap || horizontalFit); - heightExceeded = q->height() <= 0 && (multilineElide || verticalFit); + widthExceeded = availableWidth() <= 0 && (singlelineElide || canWrap || horizontalFit); + heightExceeded = availableHeight() <= 0 && (multilineElide || verticalFit); QRectF br; @@ -921,7 +1001,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) bool wasInLayout = internalWidthUpdate; internalWidthUpdate = true; - q->setImplicitSize(naturalWidth, naturalHeight); + q->setImplicitSize(naturalWidth + q->leftPadding() + q->rightPadding(), naturalHeight + q->topPadding() + q->bottomPadding()); internalWidthUpdate = wasInLayout; // Update any variables that are dependent on the validity of the width or height. @@ -938,8 +1018,11 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) const qreal oldWidth = lineWidth; const qreal oldHeight = maxHeight; - lineWidth = q->widthValid() && q->width() > 0 ? q->width() : naturalWidth; - maxHeight = q->heightValid() ? q->height() : FLT_MAX; + const qreal availWidth = availableWidth(); + const qreal availHeight = availableHeight(); + + lineWidth = q->widthValid() && availWidth > 0 ? availWidth : naturalWidth; + maxHeight = q->heightValid() ? availHeight : FLT_MAX; // If the width of the item has changed and it's possible the result of wrapping, // eliding, scaling has changed, or the text is not left aligned do another layout. @@ -992,7 +1075,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) && (q->heightValid() || (maximumLineCountValid && canWrap)); const qreal oldHeight = maxHeight; - maxHeight = q->heightValid() ? q->height() : FLT_MAX; + maxHeight = q->heightValid() ? availableHeight() : FLT_MAX; // If the height of the item has changed and it's possible the result of eliding, // line count truncation or scaling has changed, do another layout. if ((maxHeight < qMin(oldHeight, naturalHeight) || (heightExceeded && maxHeight > oldHeight)) @@ -2278,7 +2361,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data d->updateType = QQuickTextPrivate::UpdateNone; - const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), height(), d->vAlign); + const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height() + d->lineHeightOffset(), d->availableHeight(), d->vAlign) + topPadding(); QQuickTextNode *node = 0; if (!oldNode) @@ -2295,11 +2378,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data const QColor linkColor = QColor::fromRgba(d->linkColor); if (d->richText) { - const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign()); + const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), d->availableWidth(), effectiveHAlign()) + leftPadding(); d->ensureDoc(); node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor); } else if (d->layedOutTextRect.width() > 0) { - const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign()); + const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, d->availableWidth(), effectiveHAlign()) + leftPadding(); int unelidedLineCount = d->lineCount; if (d->elideLayout) unelidedLineCount -= 1; @@ -2584,14 +2667,15 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const { Q_Q(const QQuickText); QPointF translatedMousePos = mousePos; - translatedMousePos.ry() -= QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), q->height(), vAlign); + translatedMousePos.rx() -= q->leftPadding(); + translatedMousePos.ry() -= q->topPadding() + QQuickTextUtil::alignedY(layedOutTextRect.height() + lineHeightOffset(), availableHeight(), vAlign); if (styledText) { QString link = anchorAt(&layout, translatedMousePos); if (link.isEmpty() && elideLayout) link = anchorAt(elideLayout, translatedMousePos); return link; } else if (richText && extra.isAllocated() && extra->doc) { - translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign()); + translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), availableWidth(), q->effectiveHAlign()); return extra->doc->documentLayout()->anchorAt(translatedMousePos); } return QString(); @@ -2809,4 +2893,124 @@ void QQuickText::invalidateFontCaches() } } +/*! + \since 5.6 + \qmlproperty real QtQuick::Text::padding + \qmlproperty real QtQuick::Text::topPadding + \qmlproperty real QtQuick::Text::leftPadding + \qmlproperty real QtQuick::Text::bottomPadding + \qmlproperty real QtQuick::Text::rightPadding + + These properties hold the padding around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ +qreal QQuickText::padding() const +{ + Q_D(const QQuickText); + return d->padding; +} + +void QQuickText::setPadding(qreal padding) +{ + Q_D(QQuickText); + if (qFuzzyCompare(d->padding, padding)) + return; + d->padding = padding; + d->updateSize(); + emit paddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitTopPadding) + emit topPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickText::resetPadding() +{ + setPadding(0); +} + +qreal QQuickText::topPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitTopPadding) + return d->extra->topPadding; + return d->padding; +} + +void QQuickText::setTopPadding(qreal padding) +{ + Q_D(QQuickText); + d->setTopPadding(padding); +} + +void QQuickText::resetTopPadding() +{ + Q_D(QQuickText); + d->setTopPadding(0, true); +} + +qreal QQuickText::leftPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitLeftPadding) + return d->extra->leftPadding; + return d->padding; +} + +void QQuickText::setLeftPadding(qreal padding) +{ + Q_D(QQuickText); + d->setLeftPadding(padding); +} + +void QQuickText::resetLeftPadding() +{ + Q_D(QQuickText); + d->setLeftPadding(0, true); +} + +qreal QQuickText::rightPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitRightPadding) + return d->extra->rightPadding; + return d->padding; +} + +void QQuickText::setRightPadding(qreal padding) +{ + Q_D(QQuickText); + d->setRightPadding(padding); +} + +void QQuickText::resetRightPadding() +{ + Q_D(QQuickText); + d->setRightPadding(0, true); +} + +qreal QQuickText::bottomPadding() const +{ + Q_D(const QQuickText); + if (d->extra.isAllocated() && d->extra->explicitBottomPadding) + return d->extra->bottomPadding; + return d->padding; +} + +void QQuickText::setBottomPadding(qreal padding) +{ + Q_D(QQuickText); + d->setBottomPadding(padding); +} + +void QQuickText::resetBottomPadding() +{ + Q_D(QQuickText); + d->setBottomPadding(0, true); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index 283e3b510b..31a7205304 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -84,6 +84,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + public: QQuickText(QQuickItem *parent=0); ~QQuickText(); @@ -204,6 +210,26 @@ public: Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + Q_SIGNALS: void textChanged(const QString &text); void linkActivated(const QString &link); @@ -231,6 +257,11 @@ Q_SIGNALS: void lineLaidOut(QQuickTextLine *line); void baseUrlChanged(); void renderTypeChanged(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h index 9a6da3736e..6f954dd8c5 100644 --- a/src/quick/items/qquicktext_p_p.h +++ b/src/quick/items/qquicktext_p_p.h @@ -87,6 +87,14 @@ public: struct ExtraData { ExtraData(); + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding; + bool explicitLeftPadding; + bool explicitRightPadding; + bool explicitBottomPadding; qreal lineHeight; QQuickTextDocumentWithImageResources *doc; QString activeLink; @@ -111,6 +119,7 @@ public: QTextLayout *elideLayout; QQuickTextLine *textLine; + qreal padding; qreal lineWidth; QRgb color; @@ -159,6 +168,14 @@ public: qreal getImplicitWidth() const Q_DECL_OVERRIDE; qreal getImplicitHeight() const Q_DECL_OVERRIDE; + qreal availableWidth() const; + qreal availableHeight() const; + + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + void ensureDoc(); QRectF setupTextLayout(qreal * const baseline); diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 8237ad10e4..0601932beb 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -699,6 +699,62 @@ Qt::InputMethodHints QQuickTextEditPrivate::effectiveInputMethodHints() const } #endif +void QQuickTextEditPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->topPadding(); + topPadding = value; + explicitTopPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + q->updateSize(); + emit q->topPaddingChanged(); + } +} + +void QQuickTextEditPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->topPadding(); + leftPadding = value; + explicitLeftPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + q->updateSize(); + emit q->leftPaddingChanged(); + if (q->isComponentComplete()) { + updateType = QQuickTextEditPrivate::UpdatePaintNode; + q->update(); + } + } +} + +void QQuickTextEditPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->topPadding(); + rightPadding = value; + explicitRightPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + q->updateSize(); + emit q->rightPaddingChanged(); + if (q->isComponentComplete()) { + updateType = QQuickTextEditPrivate::UpdatePaintNode; + q->update(); + } + } +} + +void QQuickTextEditPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextEdit); + qreal oldPadding = q->topPadding(); + bottomPadding = value; + explicitBottomPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + q->updateSize(); + emit q->bottomPaddingChanged(); + } +} + QQuickTextEdit::VAlignment QQuickTextEdit::vAlign() const { Q_D(const QQuickTextEdit); @@ -2106,7 +2162,7 @@ void QQuickTextEdit::markDirtyNodesForRange(int start, int end, int charDelta) } // mark the affected nodes as dirty - while (it != d->textNodeMap.constEnd()) { + while (it != d->textNodeMap.end()) { if ((*it)->startPos() <= end) (*it)->setDirty(); else if (charDelta) @@ -2232,7 +2288,7 @@ void QQuickTextEdit::updateSize() return; } - qreal naturalWidth = d->implicitWidth; + qreal naturalWidth = d->implicitWidth - leftPadding() - rightPadding(); qreal newWidth = d->document->idealWidth(); // ### assumes that if the width is set, the text will fill to edges @@ -2250,13 +2306,13 @@ void QQuickTextEdit::updateSize() const bool wasInLayout = d->inLayout; d->inLayout = true; - setImplicitWidth(naturalWidth); + setImplicitWidth(naturalWidth + leftPadding() + rightPadding()); d->inLayout = wasInLayout; if (d->inLayout) // probably the result of a binding loop, but by letting it return; // get this far we'll get a warning to that effect. } if (d->document->textWidth() != width()) { - d->document->setTextWidth(width()); + d->document->setTextWidth(width() - leftPadding() - rightPadding()); newWidth = d->document->idealWidth(); } //### need to confirm cost of always setting these @@ -2271,12 +2327,12 @@ void QQuickTextEdit::updateSize() // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. if (!widthValid() && !d->requireImplicitWidth) - setImplicitSize(newWidth, newHeight); + setImplicitSize(newWidth + leftPadding() + rightPadding(), newHeight + topPadding() + bottomPadding()); else - setImplicitHeight(newHeight); + setImplicitHeight(newHeight + topPadding() + bottomPadding()); - d->xoff = qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign())); - d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign); + d->xoff = leftPadding() + qMax(qreal(0), QQuickTextUtil::alignedX(d->document->size().width(), width() - leftPadding() - rightPadding(), effectiveHAlign())); + d->yoff = topPadding() + QQuickTextUtil::alignedY(d->document->size().height(), height() - topPadding() - bottomPadding(), d->vAlign); setBaselineOffset(fm.ascent() + d->yoff + d->textMargin); QSizeF size(newWidth, newHeight); @@ -2423,10 +2479,13 @@ void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event) qGuiApp->inputMethod()->show(); q->connect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), q, SLOT(q_updateAlignment())); +#endif } else { +#ifndef QT_NO_IM q->disconnect(QGuiApplication::inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)), q, SLOT(q_updateAlignment())); #endif + emit q->editingFinished(); } } @@ -2595,6 +2654,15 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected() */ /*! + \qmlsignal QtQuick::TextEdit::editingFinished() + \since 5.6 + + This signal is emitted when the text edit loses focus. + + The corresponding handler is \c onEditingFinished. +*/ + +/*! \qmlproperty string QtQuick::TextEdit::hoveredLink \since 5.2 @@ -2687,7 +2755,131 @@ void QQuickTextEdit::append(const QString &text) QString QQuickTextEdit::linkAt(qreal x, qreal y) const { Q_D(const QQuickTextEdit); - return d->control->anchorAt(QPointF(x, y)); + return d->control->anchorAt(QPointF(x + topPadding(), y + leftPadding())); +} + +/*! + \since 5.6 + \qmlproperty real QtQuick::TextEdit::padding + \qmlproperty real QtQuick::TextEdit::topPadding + \qmlproperty real QtQuick::TextEdit::leftPadding + \qmlproperty real QtQuick::TextEdit::bottomPadding + \qmlproperty real QtQuick::TextEdit::rightPadding + + These properties hold the padding around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ +qreal QQuickTextEdit::padding() const +{ + Q_D(const QQuickTextEdit); + return d->padding; +} + +void QQuickTextEdit::setPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + if (qFuzzyCompare(d->padding, padding)) + return; + d->padding = padding; + updateSize(); + if (isComponentComplete()) { + d->updateType = QQuickTextEditPrivate::UpdatePaintNode; + update(); + } + emit paddingChanged(); + if (!d->explicitTopPadding) + emit topPaddingChanged(); + if (!d->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickTextEdit::resetPadding() +{ + setPadding(0); +} + +qreal QQuickTextEdit::topPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->explicitTopPadding) + return d->topPadding; + return d->padding; +} + +void QQuickTextEdit::setTopPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setTopPadding(padding); +} + +void QQuickTextEdit::resetTopPadding() +{ + Q_D(QQuickTextEdit); + d->setTopPadding(0, true); +} + +qreal QQuickTextEdit::leftPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->explicitLeftPadding) + return d->leftPadding; + return d->padding; +} + +void QQuickTextEdit::setLeftPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setLeftPadding(padding); +} + +void QQuickTextEdit::resetLeftPadding() +{ + Q_D(QQuickTextEdit); + d->setLeftPadding(0, true); +} + +qreal QQuickTextEdit::rightPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->explicitRightPadding) + return d->rightPadding; + return d->padding; +} + +void QQuickTextEdit::setRightPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setRightPadding(padding); +} + +void QQuickTextEdit::resetRightPadding() +{ + Q_D(QQuickTextEdit); + d->setRightPadding(0, true); +} + +qreal QQuickTextEdit::bottomPadding() const +{ + Q_D(const QQuickTextEdit); + if (d->explicitBottomPadding) + return d->bottomPadding; + return d->padding; +} + +void QQuickTextEdit::setBottomPadding(qreal padding) +{ + Q_D(QQuickTextEdit); + d->setBottomPadding(padding); +} + +void QQuickTextEdit::resetBottomPadding() +{ + Q_D(QQuickTextEdit); + d->setBottomPadding(0, true); } QT_END_NAMESPACE diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index bf6763f772..f1ccd72ca9 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -91,8 +91,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged) Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) - Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument FINAL REVISION 1) + Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument CONSTANT FINAL REVISION 1) Q_PROPERTY(QString hoveredLink READ hoveredLink NOTIFY linkHovered REVISION 2) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) public: QQuickTextEdit(QQuickItem *parent=0); @@ -247,6 +252,26 @@ public: Q_REVISION(3) Q_INVOKABLE QString linkAt(qreal x, qreal y) const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + Q_SIGNALS: void textChanged(); void contentSizeChanged(); @@ -283,6 +308,12 @@ Q_SIGNALS: void baseUrlChanged(); void inputMethodHintsChanged(); void renderTypeChanged(); + Q_REVISION(6) void editingFinished(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); public Q_SLOTS: void selectAll(); diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index 0cf0f46532..20c0d1ca9c 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -84,7 +84,9 @@ public: QQuickTextEditPrivate() : color(QRgb(0xFF000000)), selectionColor(QRgb(0xFF000080)), selectedTextColor(QRgb(0xFFFFFFFF)) - , textMargin(0.0), xoff(0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0) + , textMargin(0.0), xoff(0), yoff(0), padding(0), topPadding(0), leftPadding(0), rightPadding(0), bottomPadding(0) + , explicitTopPadding(false), explicitLeftPadding(false), explicitRightPadding(false), explicitBottomPadding(false) + , font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0) , quickDocument(0), lastSelectionStart(0), lastSelectionEnd(0), lineCount(0) , hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop) , format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap) @@ -131,6 +133,11 @@ public: Qt::InputMethodHints effectiveInputMethodHints() const; #endif + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + QColor color; QColor selectionColor; QColor selectedTextColor; @@ -140,6 +147,15 @@ public: qreal textMargin; qreal xoff; qreal yoff; + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding; + bool explicitLeftPadding; + bool explicitRightPadding; + bool explicitBottomPadding; QString text; QUrl baseUrl; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index a4c61209f2..c5f3f3ffaf 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -786,8 +786,8 @@ QRectF QQuickTextInput::cursorRectangle() const QTextLine l = d->m_textLayout.lineForTextPosition(c); if (!l.isValid()) return QRectF(); - qreal x = l.cursorToX(c) - d->hscroll; - qreal y = l.y() - d->vscroll; + qreal x = l.cursorToX(c) - d->hscroll + leftPadding(); + qreal y = l.y() - d->vscroll + topPadding(); return QRectF(x, y, 1, l.height()); } @@ -910,189 +910,6 @@ void QQuickTextInput::setAutoScroll(bool b) emit autoScrollChanged(d->autoScroll); } -#ifndef QT_NO_VALIDATOR - -/*! - \qmltype IntValidator - \instantiates QIntValidator - \inqmlmodule QtQuick - \ingroup qtquick-text-utility - \brief Defines a validator for integer values - - The IntValidator type provides a validator for integer values. - - If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to - interpret the number and will accept locale specific digits, group separators, and positive - and negative signs. In addition, IntValidator is always guaranteed to accept a number - formatted according to the "C" locale. -*/ - - -QQuickIntValidator::QQuickIntValidator(QObject *parent) - : QIntValidator(parent) -{ -} - -/*! - \qmlproperty string QtQuick::IntValidator::locale - - This property holds the name of the locale used to interpret the number. - - \sa {QtQml::Qt::locale()}{Qt.locale()} -*/ - -QString QQuickIntValidator::localeName() const -{ - return locale().name(); -} - -void QQuickIntValidator::setLocaleName(const QString &name) -{ - if (locale().name() != name) { - setLocale(QLocale(name)); - emit localeNameChanged(); - } -} - -void QQuickIntValidator::resetLocaleName() -{ - QLocale defaultLocale; - if (locale() != defaultLocale) { - setLocale(defaultLocale); - emit localeNameChanged(); - } -} - -/*! - \qmlproperty int QtQuick::IntValidator::top - - This property holds the validator's highest acceptable value. - By default, this property's value is derived from the highest signed integer available (typically 2147483647). -*/ -/*! - \qmlproperty int QtQuick::IntValidator::bottom - - This property holds the validator's lowest acceptable value. - By default, this property's value is derived from the lowest signed integer available (typically -2147483647). -*/ - -/*! - \qmltype DoubleValidator - \instantiates QDoubleValidator - \inqmlmodule QtQuick - \ingroup qtquick-text-utility - \brief Defines a validator for non-integer numbers - - The DoubleValidator type provides a validator for non-integer numbers. - - Input is accepted if it contains a double that is within the valid range - and is in the correct format. - - Input is accepected but invalid if it contains a double that is outside - the range or is in the wrong format; e.g. with too many digits after the - decimal point or is empty. - - Input is rejected if it is not a double. - - Note: If the valid range consists of just positive doubles (e.g. 0.0 to - 100.0) and input is a negative double then it is rejected. If \l notation - is set to DoubleValidator.StandardNotation, and the input contains more - digits before the decimal point than a double in the valid range may have, - it is also rejected. If \l notation is DoubleValidator.ScientificNotation, - and the input is not in the valid range, it is accecpted but invalid. The - value may yet become valid by changing the exponent. -*/ - -QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent) - : QDoubleValidator(parent) -{ -} - -/*! - \qmlproperty string QtQuick::DoubleValidator::locale - - This property holds the name of the locale used to interpret the number. - - \sa {QtQml::Qt::locale()}{Qt.locale()} -*/ - -QString QQuickDoubleValidator::localeName() const -{ - return locale().name(); -} - -void QQuickDoubleValidator::setLocaleName(const QString &name) -{ - if (locale().name() != name) { - setLocale(QLocale(name)); - emit localeNameChanged(); - } -} - -void QQuickDoubleValidator::resetLocaleName() -{ - QLocale defaultLocale; - if (locale() != defaultLocale) { - setLocale(defaultLocale); - emit localeNameChanged(); - } -} - -#endif // QT_NO_VALIDATOR - -/*! - \qmlproperty real QtQuick::DoubleValidator::top - - This property holds the validator's maximum acceptable value. - By default, this property contains a value of infinity. -*/ -/*! - \qmlproperty real QtQuick::DoubleValidator::bottom - - This property holds the validator's minimum acceptable value. - By default, this property contains a value of -infinity. -*/ -/*! - \qmlproperty int QtQuick::DoubleValidator::decimals - - This property holds the validator's maximum number of digits after the decimal point. - By default, this property contains a value of 1000. -*/ -/*! - \qmlproperty enumeration QtQuick::DoubleValidator::notation - This property holds the notation of how a string can describe a number. - - The possible values for this property are: - - \list - \li DoubleValidator.StandardNotation - \li DoubleValidator.ScientificNotation (default) - \endlist - - If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2). -*/ - -/*! - \qmltype RegExpValidator - \instantiates QRegExpValidator - \inqmlmodule QtQuick - \ingroup qtquick-text-utility - \brief Provides a string validator - - The RegExpValidator type provides a validator, which counts as valid any string which - matches a specified regular expression. -*/ -/*! - \qmlproperty regExp QtQuick::RegExpValidator::regExp - - This property holds the regular expression used for validation. - - Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression - matching "a". - - By default, this property contains a regular expression with the pattern .* that matches any string. -*/ - /*! \qmlproperty Validator QtQuick::TextInput::validator @@ -1489,8 +1306,9 @@ void QQuickTextInput::positionAt(QQmlV4Function *args) const int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPosition position) const { - x += hscroll; - y += vscroll; + Q_Q(const QQuickTextInput); + x += hscroll - q->leftPadding(); + y += vscroll - q->topPadding(); QTextLine line = m_textLayout.lineAt(0); for (int i = 1; i < m_textLayout.lineCount(); ++i) { QTextLine nextLine = m_textLayout.lineAt(i); @@ -1748,7 +1566,7 @@ void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int { Q_Q(QQuickTextInput); QTextLine textLine = m_textLayout.lineForTextPosition(position + preeditCursor); - const qreal width = qMax<qreal>(0, q->width()); + const qreal width = qMax<qreal>(0, q->width() - q->leftPadding() - q->rightPadding()); qreal cix = 0; qreal widthUsed = 0; if (textLine.isValid()) { @@ -1811,7 +1629,7 @@ void QQuickTextInputPrivate::updateVerticalScroll() #ifndef QT_NO_IM const int preeditLength = m_textLayout.preeditAreaText().length(); #endif - const qreal height = qMax<qreal>(0, q->height()); + const qreal height = qMax<qreal>(0, q->height() - q->topPadding() - q->bottomPadding()); qreal heightUsed = contentSize.height(); qreal previousScroll = vscroll; @@ -1920,13 +1738,13 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData node->deleteContent(); node->setMatrix(QMatrix4x4()); - QPointF offset(0, 0); + QPointF offset(leftPadding(), topPadding()); if (d->autoScroll && d->m_textLayout.lineCount() > 0) { QFontMetricsF fm(d->font); // the y offset is there to keep the baseline constant in case we have script changes in the text. - offset = -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent()); + offset += -QPointF(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent()); } else { - offset = -QPointF(d->hscroll, d->vscroll); + offset += -QPointF(d->hscroll, d->vscroll); } if (!d->m_textLayout.text().isEmpty() @@ -2882,7 +2700,7 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const QTextLine line = layout.createLine(); line.setLineWidth(INT_MAX); - d->implicitWidth = qCeil(line.naturalTextWidth()); + d->implicitWidth = qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding(); layout.endLayout(); } @@ -2890,6 +2708,54 @@ qreal QQuickTextInputPrivate::getImplicitWidth() const return implicitWidth; } +void QQuickTextInputPrivate::setTopPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->topPadding(); + topPadding = value; + explicitTopPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateLayout(); + emit q->topPaddingChanged(); + } +} + +void QQuickTextInputPrivate::setLeftPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->leftPadding(); + leftPadding = value; + explicitLeftPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateLayout(); + emit q->leftPaddingChanged(); + } +} + +void QQuickTextInputPrivate::setRightPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->rightPadding(); + rightPadding = value; + explicitRightPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateLayout(); + emit q->rightPaddingChanged(); + } +} + +void QQuickTextInputPrivate::setBottomPadding(qreal value, bool reset) +{ + Q_Q(QQuickTextInput); + qreal oldPadding = q->bottomPadding(); + bottomPadding = value; + explicitBottomPadding = !reset; + if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding))) { + updateLayout(); + emit q->bottomPaddingChanged(); + } +} + void QQuickTextInputPrivate::updateLayout() { Q_Q(QQuickTextInput); @@ -2915,12 +2781,12 @@ void QQuickTextInputPrivate::updateLayout() line.setLineWidth(INT_MAX); const bool wasInLayout = inLayout; inLayout = true; - q->setImplicitWidth(qCeil(line.naturalTextWidth())); + q->setImplicitWidth(qCeil(line.naturalTextWidth()) + q->leftPadding() + q->rightPadding()); inLayout = wasInLayout; if (inLayout) // probably the result of a binding loop, but by letting it return; // get this far we'll get a warning to that effect. } - qreal lineWidth = q->widthValid() ? q->width() : INT_MAX; + qreal lineWidth = q->widthValid() ? q->width() - q->leftPadding() - q->rightPadding() : INT_MAX; qreal height = 0; qreal width = 0; do { @@ -2947,9 +2813,9 @@ void QQuickTextInputPrivate::updateLayout() q->update(); if (!requireImplicitWidth && !q->widthValid()) - q->setImplicitSize(width, height); + q->setImplicitSize(width + q->leftPadding() + q->rightPadding(), height + q->topPadding() + q->bottomPadding()); else - q->setImplicitHeight(height); + q->setImplicitHeight(height + q->topPadding() + q->bottomPadding()); updateBaselineOffset(); @@ -2971,13 +2837,13 @@ void QQuickTextInputPrivate::updateBaselineOffset() QFontMetricsF fm(font); qreal yoff = 0; if (q->heightValid()) { - const qreal surplusHeight = q->height() - contentSize.height(); + const qreal surplusHeight = q->height() - contentSize.height() - q->topPadding() - q->bottomPadding(); if (vAlign == QQuickTextInput::AlignBottom) yoff = surplusHeight; else if (vAlign == QQuickTextInput::AlignVCenter) yoff = surplusHeight/2; } - q->setBaselineOffset(fm.ascent() + yoff); + q->setBaselineOffset(fm.ascent() + yoff + q->topPadding()); } #ifndef QT_NO_CLIPBOARD @@ -4273,6 +4139,21 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) return; } + if (m_blinkPeriod > 0) { + if (m_blinkTimer) + q->killTimer(m_blinkTimer); + + m_blinkTimer = q->startTimer(m_blinkPeriod / 2); + + if (m_blinkStatus == 0) { + m_blinkStatus = 1; + + updateType = UpdatePaintNode; + q->polish(); + q->update(); + } + } + if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing && !m_readOnly @@ -4508,5 +4389,125 @@ void QQuickTextInput::ensureVisible(int position) updateCursorRectangle(false); } +/*! + \since 5.6 + \qmlproperty real QtQuick::TextInput::padding + \qmlproperty real QtQuick::TextInput::topPadding + \qmlproperty real QtQuick::TextInput::leftPadding + \qmlproperty real QtQuick::TextInput::bottomPadding + \qmlproperty real QtQuick::TextInput::rightPadding + + These properties hold the padding around the content. This space is reserved + in addition to the contentWidth and contentHeight. +*/ +qreal QQuickTextInput::padding() const +{ + Q_D(const QQuickTextInput); + return d->padding; +} + +void QQuickTextInput::setPadding(qreal padding) +{ + Q_D(QQuickTextInput); + if (qFuzzyCompare(d->padding, padding)) + return; + d->padding = padding; + d->updateLayout(); + emit paddingChanged(); + if (!d->explicitTopPadding) + emit topPaddingChanged(); + if (!d->explicitLeftPadding) + emit leftPaddingChanged(); + if (!d->explicitRightPadding) + emit rightPaddingChanged(); + if (!d->explicitBottomPadding) + emit bottomPaddingChanged(); +} + +void QQuickTextInput::resetPadding() +{ + setPadding(0); +} + +qreal QQuickTextInput::topPadding() const +{ + Q_D(const QQuickTextInput); + if (d->explicitTopPadding) + return d->topPadding; + return d->padding; +} + +void QQuickTextInput::setTopPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setTopPadding(padding); +} + +void QQuickTextInput::resetTopPadding() +{ + Q_D(QQuickTextInput); + d->setTopPadding(0, true); +} + +qreal QQuickTextInput::leftPadding() const +{ + Q_D(const QQuickTextInput); + if (d->explicitLeftPadding) + return d->leftPadding; + return d->padding; +} + +void QQuickTextInput::setLeftPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setLeftPadding(padding); +} + +void QQuickTextInput::resetLeftPadding() +{ + Q_D(QQuickTextInput); + d->setLeftPadding(0, true); +} + +qreal QQuickTextInput::rightPadding() const +{ + Q_D(const QQuickTextInput); + if (d->explicitRightPadding) + return d->rightPadding; + return d->padding; +} + +void QQuickTextInput::setRightPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setRightPadding(padding); +} + +void QQuickTextInput::resetRightPadding() +{ + Q_D(QQuickTextInput); + d->setRightPadding(0, true); +} + +qreal QQuickTextInput::bottomPadding() const +{ + Q_D(const QQuickTextInput); + if (d->explicitBottomPadding) + return d->bottomPadding; + return d->padding; +} + +void QQuickTextInput::setBottomPadding(qreal padding) +{ + Q_D(QQuickTextInput); + d->setBottomPadding(padding); +} + +void QQuickTextInput::resetBottomPadding() +{ + Q_D(QQuickTextInput); + d->setBottomPadding(0, true); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 3bcbe0fa25..333f55b35f 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -96,6 +96,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged) Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged) + Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged REVISION 6) + Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged REVISION 6) + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged REVISION 6) + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged REVISION 6) + Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged REVISION 6) + public: QQuickTextInput(QQuickItem * parent=0); ~QQuickTextInput(); @@ -260,6 +266,26 @@ public: qreal contentWidth() const; qreal contentHeight() const; + qreal padding() const; + void setPadding(qreal padding); + void resetPadding(); + + qreal topPadding() const; + void setTopPadding(qreal padding); + void resetTopPadding(); + + qreal leftPadding() const; + void setLeftPadding(qreal padding); + void resetLeftPadding(); + + qreal rightPadding() const; + void setRightPadding(qreal padding); + void resetRightPadding(); + + qreal bottomPadding() const; + void setBottomPadding(qreal padding); + void resetBottomPadding(); + Q_SIGNALS: void textChanged(); void cursorPositionChanged(); @@ -300,6 +326,11 @@ Q_SIGNALS: void contentSizeChanged(); void inputMethodHintsChanged(); void renderTypeChanged(); + Q_REVISION(6) void paddingChanged(); + Q_REVISION(6) void topPaddingChanged(); + Q_REVISION(6) void leftPaddingChanged(); + Q_REVISION(6) void rightPaddingChanged(); + Q_REVISION(6) void bottomPaddingChanged(); private: void invalidateFontCaches(); @@ -360,46 +391,8 @@ private: Q_DECLARE_PRIVATE(QQuickTextInput) }; -#ifndef QT_NO_VALIDATOR -class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator -{ - Q_OBJECT - Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) -public: - QQuickIntValidator(QObject *parent = 0); - - QString localeName() const; - void setLocaleName(const QString &name); - void resetLocaleName(); - -Q_SIGNALS: - void localeNameChanged(); -}; - -class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator -{ - Q_OBJECT - Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) -public: - QQuickDoubleValidator(QObject *parent = 0); - - QString localeName() const; - void setLocaleName(const QString &name); - void resetLocaleName(); - -Q_SIGNALS: - void localeNameChanged(); -}; -#endif - QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickTextInput) -#ifndef QT_NO_VALIDATOR -QML_DECLARE_TYPE(QValidator) -QML_DECLARE_TYPE(QQuickIntValidator) -QML_DECLARE_TYPE(QQuickDoubleValidator) -QML_DECLARE_TYPE(QRegExpValidator) -#endif #endif // QQUICKTEXTINPUT_P_H diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 3038573bb3..25ee2e79ce 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -74,6 +74,15 @@ public: QQuickTextInputPrivate() : hscroll(0) , vscroll(0) + , padding(0) + , topPadding(0) + , leftPadding(0) + , rightPadding(0) + , bottomPadding(0) + , explicitTopPadding(false) + , explicitLeftPadding(false) + , explicitRightPadding(false) + , explicitBottomPadding(false) , cursorItem(0) , textNode(0) , m_maskData(0) @@ -189,6 +198,16 @@ public: qreal hscroll; qreal vscroll; + qreal padding; + qreal topPadding; + qreal leftPadding; + qreal rightPadding; + qreal bottomPadding; + bool explicitTopPadding; + bool explicitLeftPadding; + bool explicitRightPadding; + bool explicitBottomPadding; + QTextLayout m_textLayout; QString m_text; QString m_inputMask; @@ -420,6 +439,11 @@ public: qreal getImplicitWidth() const Q_DECL_OVERRIDE; + void setTopPadding(qreal value, bool reset = false); + void setLeftPadding(qreal value, bool reset = false); + void setRightPadding(qreal value, bool reset = false); + void setBottomPadding(qreal value, bool reset = false); + private: void removeSelectedText(); void internalSetText(const QString &txt, int pos = -1, bool edited = true); diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index 5b5413a4ba..6582e3ad40 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -345,6 +345,9 @@ QQuickView::Status QQuickView::status() const if (!d->component) return QQuickView::Null; + if (d->component->status() == QQmlComponent::Ready && !d->root) + return QQuickView::Error; + return QQuickView::Status(d->component->status()); } @@ -364,6 +367,10 @@ QList<QQmlError> QQuickView::errors() const QQmlError error; error.setDescription(QLatin1String("QQuickView: invalid qml engine.")); errs << error; + } else if (d->component->status() == QQmlComponent::Ready && !d->root) { + QQmlError error; + error.setDescription(QLatin1String("QQuickView: invalid root object.")); + errs << error; } return errs; @@ -501,14 +508,15 @@ void QQuickViewPrivate::setRootObject(QObject *obj) if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) { root = sgItem; sgItem->setParentItem(q->QQuickWindow::contentItem()); + } else if (qobject_cast<QWindow *>(obj)) { + qWarning() << "QQuickView does not support using windows as a root item." << endl + << endl + << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl; } else { qWarning() << "QQuickView only supports loading of root objects that derive from QQuickItem." << endl << endl - << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl - << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl - << endl - << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl - << "QDeclarativeView class in the Qt Quick 1 module." << endl; + << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl + << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl; delete obj; root = 0; } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 84b585e3b5..ee2556af64 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -3308,12 +3308,7 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const QImage QQuickWindow::grabWindow() { Q_D(QQuickWindow); - if (!isVisible()) { - - if (d->context->openglContext()) { - qWarning("QQuickWindow::grabWindow: scene graph already in use"); - return QImage(); - } + if (!isVisible() && !d->context->openglContext()) { if (!handle() || !size().isValid()) { qWarning("QQuickWindow::grabWindow: window must be created and have a valid size"); @@ -4116,6 +4111,7 @@ void QQuickWindow::resetOpenGLState() \value BeforeRenderingStage Before rendering. \value AfterRenderingStage After rendering. \value AfterSwapStage After the frame is swapped. + \value NoStage As soon as possible. This value was added in Qt 5.6. \sa {Scene Graph and Rendering} */ @@ -4141,8 +4137,17 @@ void QQuickWindow::resetOpenGLState() If the rendering is happening on a different thread, then the job will happen on the rendering thread. - \note This function does not trigger rendering; the job - will be stored run until rendering is triggered elsewhere. + If \a stage is \l NoStage, \a job will be run at the earliest opportunity + whenever the render thread is not busy rendering a frame. If there is no + OpenGL context available or the window is not exposed at the time the job is + either posted or handled, it is deleted without executing the run() method. + If a non-threaded renderer is in use, the run() method of the job is executed + synchronously. + The OpenGL context is changed to the renderer context before executing a + \l NoStage job. + + \note This function does not trigger rendering; the jobs targeting any other + stage than NoStage will be stored run until rendering is triggered elsewhere. To force the job to run earlier, call QQuickWindow::update(); \sa beforeRendering(), afterRendering(), beforeSynchronizing(), @@ -4154,16 +4159,22 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage) Q_D(QQuickWindow); d->renderJobMutex.lock(); - if (stage == BeforeSynchronizingStage) + if (stage == BeforeSynchronizingStage) { d->beforeSynchronizingJobs << job; - else if (stage == AfterSynchronizingStage) + } else if (stage == AfterSynchronizingStage) { d->afterSynchronizingJobs << job; - else if (stage == BeforeRenderingStage) + } else if (stage == BeforeRenderingStage) { d->beforeRenderingJobs << job; - else if (stage == AfterRenderingStage) + } else if (stage == AfterRenderingStage) { d->afterRenderingJobs << job; - else if (stage == AfterSwapStage) + } else if (stage == AfterSwapStage) { d->afterSwapJobs << job; + } else if (stage == NoStage) { + if (isExposed()) + d->windowManager->postJob(this, job); + else + delete job; + } d->renderJobMutex.unlock(); } diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index f7a1956120..1a1d44c3b4 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -77,7 +77,8 @@ public: AfterSynchronizingStage, BeforeRenderingStage, AfterRenderingStage, - AfterSwapStage + AfterSwapStage, + NoStage }; Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 63938d50a9..81e72b7946 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -1081,6 +1081,9 @@ void Renderer::nodeWasRemoved(Node *node) if (e) { e->removed = true; m_elementsToDelete.add(e); + + if (m_renderNodeElements.isEmpty()) + m_useDepthBuffer = context()->openglContext()->format().depthBufferSize() > 0; } } @@ -2547,8 +2550,15 @@ void Renderer::render() QSGNodeDumper::dump(rootNode()); } - if (Q_UNLIKELY(debug_render() || debug_build())) { + QElapsedTimer timer; + quint64 timeRenderLists = 0; + quint64 timePrepareOpaque = 0; + quint64 timePrepareAlpha = 0; + quint64 timeSorting = 0; + quint64 timeUploadOpaque = 0; + quint64 timeUploadAlpha = 0; + if (Q_UNLIKELY(debug_render() || debug_build())) { QByteArray type("rebuild:"); if (m_rebuild == 0) type += " none"; @@ -2564,6 +2574,7 @@ void Renderer::render() } qDebug() << "Renderer::render()" << this << type; + timer.start(); } if (m_vao) @@ -2590,6 +2601,7 @@ void Renderer::render() } } } + if (Q_UNLIKELY(debug_render())) timeRenderLists = timer.restart(); for (int i=0; i<m_opaqueBatches.size(); ++i) m_opaqueBatches.at(i)->cleanupRemovedElements(); @@ -2602,7 +2614,9 @@ void Renderer::render() if (m_rebuild & BuildBatches) { prepareOpaqueBatches(); + if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timer.restart(); prepareAlphaBatches(); + if (Q_UNLIKELY(debug_render())) timePrepareAlpha = timer.restart(); if (Q_UNLIKELY(debug_build())) { qDebug() << "Opaque Batches:"; @@ -2622,8 +2636,11 @@ void Renderer::render() } } } + } else { + if (Q_UNLIKELY(debug_render())) timePrepareOpaque = timePrepareAlpha = timer.restart(); } + deleteRemovedElements(); if (m_rebuild != 0) { @@ -2639,6 +2656,8 @@ void Renderer::render() m_zRange = 1.0 / (m_nextRenderOrder); } + if (Q_UNLIKELY(debug_render())) timeSorting = timer.restart(); + int largestVBO = 0; #ifdef QSG_SEPARATE_INDEX_BUFFER int largestIBO = 0; @@ -2653,6 +2672,8 @@ void Renderer::render() #endif uploadBatch(b); } + if (Q_UNLIKELY(debug_render())) timeUploadOpaque = timer.restart(); + if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Alpha Batches:"; for (int i=0; i<m_alphaBatches.size(); ++i) { @@ -2663,6 +2684,7 @@ void Renderer::render() largestIBO = qMax(b->ibo.size, largestIBO); #endif } + if (Q_UNLIKELY(debug_render())) timeUploadAlpha = timer.restart(); if (largestVBO * 2 < m_vertexUploadPool.size()) m_vertexUploadPool.resize(largestVBO * 2); @@ -2673,6 +2695,15 @@ void Renderer::render() renderBatches(); + if (Q_UNLIKELY(debug_render())) { + qDebug(" -> times: build: %d, prepare(opaque/alpha): %d/%d, sorting: %d, upload(opaque/alpha): %d/%d, render: %d", + (int) timeRenderLists, + (int) timePrepareOpaque, (int) timePrepareAlpha, + (int) timeSorting, + (int) timeUploadOpaque, (int) timeUploadAlpha, + (int) timer.elapsed()); + } + m_rebuild = 0; m_renderOrderRebuildLower = -1; m_renderOrderRebuildUpper = -1; diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 102985f2c7..0c4b2f9af9 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -104,8 +104,11 @@ char const *const *QSGTextMaskShader::attributeNames() const } QSGTextMaskShader::QSGTextMaskShader(QFontEngine::GlyphFormat glyphFormat) - : QSGMaterialShader(*new QSGMaterialShaderPrivate), - m_glyphFormat(glyphFormat) + : QSGMaterialShader(*new QSGMaterialShaderPrivate) + , m_matrix_id(-1) + , m_color_id(-1) + , m_textureScale_id(-1) + , m_glyphFormat(glyphFormat) { setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/textmask.vert")); setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/textmask.frag")); diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index 422e31ad96..6f4b85a5b9 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -80,6 +80,11 @@ QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader() : QSGMaterialShader(), m_fontScale(1.0) , m_matrixScale(1.0) + , m_matrix_id(-1) + , m_textureScale_id(-1) + , m_alphaMin_id(-1) + , m_alphaMax_id(-1) + , m_color_id(-1) , m_lastAlphaMin(-1) , m_lastAlphaMax(-1) { @@ -260,6 +265,7 @@ protected: DistanceFieldStyledTextMaterialShader::DistanceFieldStyledTextMaterialShader() : QSGDistanceFieldTextMaterialShader() + , m_styleColor_id(-1) { } @@ -330,6 +336,8 @@ protected: DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader() : DistanceFieldStyledTextMaterialShader() + , m_outlineAlphaMax0_id(-1) + , m_outlineAlphaMax1_id(-1) { setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldoutlinetext.frag")); } @@ -411,6 +419,7 @@ protected: DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader() : DistanceFieldStyledTextMaterialShader() + , m_shift_id(-1) { setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.vert")); setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.frag")); @@ -489,6 +498,8 @@ private: QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader() : QSGDistanceFieldTextMaterialShader() + , m_fontScale_id(-1) + , m_vecDelta_id(-1) { setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert")); setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag")); diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index ec9c3c39f9..6c7fb89b6f 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -101,6 +101,22 @@ void QSGRenderLoop::cleanup() s_instance = 0; } +/*! + * Non-threaded render loops immediately run the job if there is a context. + */ +void QSGRenderLoop::postJob(QQuickWindow *window, QRunnable *job) +{ + Q_ASSERT(window); + Q_ASSERT(job); + + if (window->openglContext()) { + window->openglContext()->makeCurrent(window); + job->run(); + } + + delete job; +} + class QSGGuiThreadRenderLoop : public QSGRenderLoop { Q_OBJECT diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h index 4293015b96..3336731fda 100644 --- a/src/quick/scenegraph/qsgrenderloop_p.h +++ b/src/quick/scenegraph/qsgrenderloop_p.h @@ -45,6 +45,7 @@ class QQuickWindow; class QSGContext; class QSGRenderContext; class QAnimationDriver; +class QRunnable; class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject { @@ -72,6 +73,7 @@ public: virtual QSGRenderContext *createRenderContext(QSGContext *) const = 0; virtual void releaseResources(QQuickWindow *window) = 0; + virtual void postJob(QQuickWindow *window, QRunnable *job); void addWindow(QQuickWindow *win) { m_windows.insert(win); } void removeWindow(QQuickWindow *win) { m_windows.remove(win); } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 56637387df..074e7633da 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -147,6 +147,9 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4); // called. const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5); +// Passed by the window when there is a render job to run +const QEvent::Type WM_PostJob = QEvent::Type(QEvent::User + 6); + template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window) { for (int i=0; i<list.size(); ++i) { @@ -200,6 +203,14 @@ public: QImage *image; }; +class WMJobEvent : public WMWindowEvent +{ +public: + WMJobEvent(QQuickWindow *c, QRunnable *postedJob) + : WMWindowEvent(c, WM_PostJob), job(postedJob) {} + ~WMJobEvent() { delete job; } + QRunnable *job; +}; class QSGRenderThreadEventQueue : public QQueue<QEvent *> { @@ -345,7 +356,6 @@ bool QSGRenderThread::event(QEvent *e) if (window) { QQuickWindowPrivate::get(window)->fireAboutToStop(); qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window removed"; - gl->doneCurrent(); window = 0; } waitCondition.wakeOne(); @@ -396,20 +406,21 @@ bool QSGRenderThread::event(QEvent *e) case WM_Grab: { qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Grab"; WMGrabEvent *ce = static_cast<WMGrabEvent *>(e); - Q_ASSERT(ce->window == window); + Q_ASSERT(ce->window); + Q_ASSERT(ce->window == window || !window); mutex.lock(); - if (window) { - gl->makeCurrent(window); + if (ce->window) { + gl->makeCurrent(ce->window); qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync scene graph"; - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + QQuickWindowPrivate *d = QQuickWindowPrivate::get(ce->window); d->syncSceneGraph(); qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering scene graph"; - QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize); + QQuickWindowPrivate::get(ce->window)->renderSceneGraph(ce->window->size()); qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- grabbing result"; - *ce->image = qt_gl_read_framebuffer(windowSize * window->effectiveDevicePixelRatio(), false, false); + *ce->image = qt_gl_read_framebuffer(windowSize * ce->window->effectiveDevicePixelRatio(), false, false); } qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- waking gui to handle result"; waitCondition.wakeOne(); @@ -417,6 +428,20 @@ bool QSGRenderThread::event(QEvent *e) return true; } + case WM_PostJob: { + qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_PostJob"; + WMJobEvent *ce = static_cast<WMJobEvent *>(e); + Q_ASSERT(ce->window == window); + if (window) { + gl->makeCurrent(window); + ce->job->run(); + delete ce->job; + ce->job = 0; + qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- job done"; + } + return true; + } + case WM_RequestRepaint: qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint"; // When GUI posts this event, it is followed by a polishAndSync, so we mustn't @@ -1239,6 +1264,18 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) return result; } +/*! + * Posts a new job event to the render thread. + * Returns true if posting succeeded. + */ +void QSGThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job) +{ + Window *w = windowFor(m_windows, window); + if (w && w->thread && w->thread->window) + w->thread->postEvent(new WMJobEvent(window, job)); + else + delete job; +} #include "qsgthreadedrenderloop.moc" diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index d5ffbf10a3..67df9dcd31 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -71,6 +71,7 @@ public: void releaseResources(QQuickWindow *window); bool event(QEvent *); + void postJob(QQuickWindow *window, QRunnable *job); bool interleaveIncubation() const; diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 8b617e5e3f..016f41d436 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -126,9 +126,8 @@ void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, m_controller->startJob(this, m_job); } else if (newState == Stopped) { syncBackCurrentValues(); - if (m_internalState == State_Starting) - m_internalState = State_Stopped; - else if (m_controller) { + m_internalState = State_Stopped; + if (m_controller) { m_controller->stopJob(this, m_job); } } diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index 1cffae17db..34c106e89b 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -151,7 +151,6 @@ protected: int m_duration; - uint m_feedback : 1; uint m_isTransform : 1; uint m_isUniform : 1; uint m_hasBeenRunning : 1; diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index a231209cd0..70fc3a0973 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -33,6 +33,9 @@ #include "qquickimageprovider.h" +#include "qquickpixmapcache_p.h" +#include <QtQuick/private/qsgcontext_p.h> + QT_BEGIN_NAMESPACE class QQuickImageProviderPrivate @@ -95,6 +98,23 @@ QImage QQuickTextureFactory::image() const return QImage(); } +/*! + Returns a QQuickTextureFactory holding given the image. + + \since 5.6 + */ + +QQuickTextureFactory *QQuickTextureFactory::textureFactoryForImage(const QImage &image) +{ + if (image.isNull()) + return 0; + QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image); + if (texture) + return texture; + return new QQuickDefaultTextureFactory(image); +} + + /*! \fn QSGTexture *QQuickTextureFactory::createTexture(QQuickWindow *window) const @@ -118,6 +138,67 @@ QImage QQuickTextureFactory::image() const /*! + \class QQuickImageResponse + \since 5.6 + \brief The QQuickImageResponse class provides an interface for asynchronous image loading in QQuickAsyncImageProvider. + \inmodule QtQuick + + The purpose of an image response is to provide a way for image provider jobs to be executed + in an asynchronous way. + + Responses are deleted via \l deleteLater once the finished() signal has been emitted. + If you are using QRunnable as base for your QQuickImageResponse + ensure automatic deletion is disabled. + + \sa QQuickImageProvider +*/ + +/*! + Constructs the image response +*/ +QQuickImageResponse::QQuickImageResponse() +{ +} + +/*! + Destructs the image response +*/ +QQuickImageResponse::~QQuickImageResponse() +{ +} + +/*! + Returns the error string for the job execution. An empty string means no error. +*/ +QString QQuickImageResponse::errorString() const +{ + return QString(); +} + +/*! + This method is used to communicate that the response is no longer required by the engine. + + It may be reimplemented to cancel a request in the provider side, however, it is not mandatory. +*/ +void QQuickImageResponse::cancel() +{ +} + +/*! + \fn void QQuickImageResponse::finished() + + Signals that the job execution has finished (be it successfully, because an error happened or because it was cancelled). + */ + +/*! + \fn QQuickTextureFactory *QQuickImageResponse::textureFactory() const + + Returns the texture factory the job. You can use QQuickTextureFactory::textureFactoryForImage + if your provider works with QImage + */ + + +/*! \class QQuickImageProvider \since 5.0 \inmodule QtQuick @@ -213,7 +294,7 @@ QImage QQuickTextureFactory::image() const To force asynchronous image loading, even for image sources that do not have the \c asynchronous property set to \c true, you may pass the - \c QQuickImageProvider::ForceAsynchronousImageLoading flag to the image + \c QQmlImageProviderBase::ForceAsynchronousImageLoading flag to the image provider constructor. This ensures that all image requests for the provider are handled in a separate thread. @@ -223,6 +304,12 @@ QImage QQuickTextureFactory::image() const if \l {Image::}{asynchronous} is set to \c true, the value is ignored and the image is loaded synchronously. + Asynchronous image loading for providers of type other than ImageResponse are + executed on a single thread per engine basis. That means that a slow image provider + will block the loading of any other request. To avoid that we suggest using QQuickAsyncImageProvider + and implement threading on the provider side via a \c QThreadPool or similar. + See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation. + \section2 Image caching @@ -365,5 +452,41 @@ QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSi return 0; } +/*! + \class QQuickAsyncImageProvider + \since 5.6 + \inmodule QtQuick + \brief The QQuickAsyncImageProvider class provides an interface for for asynchronous control of QML image requests. + + \sa QQuickImageProvider +*/ +QQuickAsyncImageProvider::QQuickAsyncImageProvider() + : QQuickImageProvider(ImageResponse, ForceAsynchronousImageLoading) + , d(0) // just as a placeholder in case we need it for the future +{ + Q_UNUSED(d); +} + +QQuickAsyncImageProvider::~QQuickAsyncImageProvider() +{ +} + +/*! + \fn QQuickImageResponse *QQuickAsyncImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize) + + Implement this method to return the job that will provide the texture with \a id. + + The \a id is the requested image source, with the "image:" scheme and + provider identifier removed. For example, if the image \l{Image::}{source} + was "image://myprovider/icons/home", the given \a id would be "icons/home". + + The \a requestedSize corresponds to the \l {Image::sourceSize} requested by + an Image item. If \a requestedSize is a valid size, the image + returned should be of that size. + + \note this method may be called by multiple threads, so ensure the + implementation of this method is reentrant. +*/ + QT_END_NAMESPACE diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h index a2b510f606..cc03eb0fa0 100644 --- a/src/quick/util/qquickimageprovider.h +++ b/src/quick/util/qquickimageprovider.h @@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE class QQuickImageProviderPrivate; +class QQuickAsyncImageProviderPrivate; class QSGTexture; class QQuickWindow; @@ -56,6 +57,25 @@ public: virtual QSize textureSize() const = 0; virtual int textureByteCount() const = 0; virtual QImage image() const; + + static QQuickTextureFactory *textureFactoryForImage(const QImage &image); +}; + +class Q_QUICK_EXPORT QQuickImageResponse : public QObject +{ +Q_OBJECT +public: + QQuickImageResponse(); + virtual ~QQuickImageResponse(); + + virtual QQuickTextureFactory *textureFactory() const = 0; + virtual QString errorString() const; + +public Q_SLOTS: + virtual void cancel(); + +Q_SIGNALS: + void finished(); }; class Q_QUICK_EXPORT QQuickImageProvider : public QQmlImageProviderBase @@ -81,6 +101,18 @@ private: QQuickImageProviderPrivate *d; }; +class Q_QUICK_EXPORT QQuickAsyncImageProvider : public QQuickImageProvider +{ +public: + QQuickAsyncImageProvider(); + virtual ~QQuickAsyncImageProvider(); + + virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) = 0; + +private: + QQuickAsyncImageProviderPrivate *d; +}; + QT_END_NAMESPACE #endif // QQUICKIMAGEPROVIDER_H diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index ddf2ae2393..f36d06d00d 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -44,7 +44,6 @@ #include <qpa/qplatformintegration.h> #include <QtQuick/private/qsgtexture_p.h> -#include <QtQuick/private/qsgcontext_p.h> #include <QQuickWindow> #include <QCoreApplication> @@ -67,7 +66,7 @@ #include <private/qquickprofiler_p.h> -#define IMAGEREQUEST_MAX_REQUEST_COUNT 8 +#define IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT 8 #define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16 #define CACHE_EXPIRE_TIME 30 #define CACHE_REMOVAL_FRACTION 4 @@ -115,16 +114,6 @@ QSGTexture *QQuickDefaultTextureFactory::createTexture(QQuickWindow *window) con return t; } -static QQuickTextureFactory *textureFactoryForImage(const QImage &image) -{ - if (image.isNull()) - return 0; - QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image); - if (texture) - return texture; - return new QQuickDefaultTextureFactory(image); -} - class QQuickPixmapReader; class QQuickPixmapData; class QQuickPixmapReply : public QObject @@ -181,6 +170,7 @@ public: virtual bool event(QEvent *e); private slots: void networkRequestDone(); + void asyncResponseFinished(); private: QQuickPixmapReader *reader; }; @@ -205,8 +195,9 @@ protected: private: friend class QQuickPixmapReaderThreadObject; void processJobs(); - void processJob(QQuickPixmapReply *, const QUrl &, const QSize &, AutoTransform); + void processJob(QQuickPixmapReply *, const QUrl &, const QString &, AutoTransform, QQuickImageProvider::ImageType, QQuickImageProvider *); void networkRequestDone(QNetworkReply *); + void asyncResponseFinished(QQuickImageResponse *); QList<QQuickPixmapReply*> jobs; QList<QQuickPixmapReply*> cancelled; @@ -220,7 +211,8 @@ private: QNetworkAccessManager *networkAccessManager(); QNetworkAccessManager *accessManager; - QHash<QNetworkReply*,QQuickPixmapReply*> replies; + QHash<QNetworkReply*,QQuickPixmapReply*> networkJobs; + QHash<QQuickImageResponse*,QQuickPixmapReply*> asyncResponses; static int replyDownloadProgress; static int replyFinished; @@ -439,8 +431,8 @@ QQuickPixmapReader::~QQuickPixmapReader() delete reply; } jobs.clear(); - QList<QQuickPixmapReply*> activeJobs = replies.values(); - foreach (QQuickPixmapReply *reply, activeJobs) { + QList<QQuickPixmapReply*> activeJobs = networkJobs.values() + asyncResponses.values(); + foreach (QQuickPixmapReply *reply, activeJobs ) { if (reply->loading) { cancelled.append(reply); reply->data = 0; @@ -455,7 +447,7 @@ QQuickPixmapReader::~QQuickPixmapReader() void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) { - QQuickPixmapReply *job = replies.take(reply); + QQuickPixmapReply *job = networkJobs.take(reply); if (job) { job->redirectCount++; @@ -472,7 +464,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress); QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone); - replies.insert(reply, job); + networkJobs.insert(reply, job); return; } } @@ -494,7 +486,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) // send completion event to the QQuickPixmapReply mutex.lock(); if (!cancelled.contains(job)) - job->postReply(error, errorString, readSize, textureFactoryForImage(image)); + job->postReply(error, errorString, readSize, QQuickTextureFactory::textureFactoryForImage(image)); mutex.unlock(); } reply->deleteLater(); @@ -503,6 +495,32 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) threadObject->processJobs(); } +void QQuickPixmapReader::asyncResponseFinished(QQuickImageResponse *response) +{ + QQuickPixmapReply *job = asyncResponses.take(response); + + if (job) { + QQuickTextureFactory *t = 0; + QQuickPixmapReply::ReadError error = QQuickPixmapReply::NoError; + QString errorString; + QSize readSize; + if (!response->errorString().isEmpty()) { + error = QQuickPixmapReply::Loading; + errorString = response->errorString(); + } else { + t = response->textureFactory(); + } + mutex.lock(); + if (!cancelled.contains(job)) + job->postReply(error, errorString, t->textureSize(), t); + mutex.unlock(); + } + response->deleteLater(); + + // kick off event loop again incase we have dropped below max request count + threadObject->processJobs(); +} + QQuickPixmapReaderThreadObject::QQuickPixmapReaderThreadObject(QQuickPixmapReader *i) : reader(i) { @@ -529,6 +547,12 @@ void QQuickPixmapReaderThreadObject::networkRequestDone() reader->networkRequestDone(reply); } +void QQuickPixmapReaderThreadObject::asyncResponseFinished() +{ + QQuickImageResponse *response = static_cast<QQuickImageResponse *>(sender()); + reader->asyncResponseFinished(response); +} + void QQuickPixmapReader::processJobs() { QMutexLocker locker(&mutex); @@ -538,16 +562,22 @@ void QQuickPixmapReader::processJobs() return; // Nothing else to do // Clean cancelled jobs - if (cancelled.count()) { + if (!cancelled.isEmpty()) { for (int i = 0; i < cancelled.count(); ++i) { QQuickPixmapReply *job = cancelled.at(i); - QNetworkReply *reply = replies.key(job, 0); + QNetworkReply *reply = networkJobs.key(job, 0); if (reply) { - replies.remove(reply); + networkJobs.remove(reply); if (reply->isRunning()) { // cancel any jobs already started reply->close(); } + } else { + QQuickImageResponse *asyncResponse = asyncResponses.key(job); + if (asyncResponse) { + asyncResponses.remove(asyncResponse); + asyncResponse->cancel(); + } } PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url)); // deleteLater, since not owned by this thread @@ -560,27 +590,34 @@ void QQuickPixmapReader::processJobs() // Find a job we can use bool usableJob = false; for (int i = jobs.count() - 1; !usableJob && i >= 0; i--) { - QQuickPixmapReply *runningJob = jobs[i]; - const QUrl url = runningJob->url; + QQuickPixmapReply *job = jobs[i]; + const QUrl url = job->url; + QString localFile; + QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid; + QQuickImageProvider *provider = 0; if (url.scheme() == QLatin1String("image")) { + provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url))); + if (provider) + imageType = provider->imageType(); + usableJob = true; } else { - const QString localFile = QQmlFile::urlToLocalFileOrQrc(url); - usableJob = !localFile.isEmpty() || replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT; + localFile = QQmlFile::urlToLocalFileOrQrc(url); + usableJob = !localFile.isEmpty() || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT; } + if (usableJob) { jobs.removeAt(i); - runningJob->loading = true; + job->loading = true; PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url)); - QSize requestSize = runningJob->requestSize; - AutoTransform autoTransform = runningJob->autoTransform; + AutoTransform autoTransform = job->autoTransform; locker.unlock(); - processJob(runningJob, url, requestSize, autoTransform); + processJob(job, url, localFile, autoTransform, imageType, provider); locker.relock(); } } @@ -591,79 +628,97 @@ void QQuickPixmapReader::processJobs() } } -void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, - const QSize &requestSize, AutoTransform autoTransform) +void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, const QString &localFile, + AutoTransform autoTransform, QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider) { // fetch if (url.scheme() == QLatin1String("image")) { // Use QQuickImageProvider QSize readSize; - QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid; - QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url))); - if (provider) - imageType = provider->imageType(); + switch (imageType) { + case QQuickImageProvider::Invalid: + { + QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()); + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(QQuickPixmapReply::Loading, errorStr, readSize, 0); + mutex.unlock(); + break; + } - if (imageType == QQuickImageProvider::Invalid) { - QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::Loading; - QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()); - QImage image; - mutex.lock(); - if (!cancelled.contains(runningJob)) - runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image)); - mutex.unlock(); - } else if (imageType == QQuickImageProvider::Image) { - QImage image = provider->requestImage(imageId(url), &readSize, requestSize); - QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; - QString errorStr; - if (image.isNull()) { - errorCode = QQuickPixmapReply::Loading; - errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString()); + case QQuickImageProvider::Image: + { + QImage image = provider->requestImage(imageId(url), &readSize, runningJob->requestSize); + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; + QString errorStr; + if (image.isNull()) { + errorCode = QQuickPixmapReply::Loading; + errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString()); + } + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image)); + mutex.unlock(); + break; } - mutex.lock(); - if (!cancelled.contains(runningJob)) - runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image)); - mutex.unlock(); - } else if (imageType == QQuickImageProvider::Pixmap) { - const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize); - QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; - QString errorStr; - if (pixmap.isNull()) { - errorCode = QQuickPixmapReply::Loading; - errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString()); + + case QQuickImageProvider::Pixmap: + { + const QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, runningJob->requestSize); + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; + QString errorStr; + if (pixmap.isNull()) { + errorCode = QQuickPixmapReply::Loading; + errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString()); + } + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage())); + mutex.unlock(); + break; } - mutex.lock(); - if (!cancelled.contains(runningJob)) - runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(pixmap.toImage())); - mutex.unlock(); - } else { - QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, requestSize); - QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; - QString errorStr; - if (!t) { - errorCode = QQuickPixmapReply::Loading; - errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString()); + + case QQuickImageProvider::Texture: + { + QQuickTextureFactory *t = provider->requestTexture(imageId(url), &readSize, runningJob->requestSize); + QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; + QString errorStr; + if (!t) { + errorCode = QQuickPixmapReply::Loading; + errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString()); + } + mutex.lock(); + if (!cancelled.contains(runningJob)) + runningJob->postReply(errorCode, errorStr, readSize, t); + else + delete t; + mutex.unlock(); + break; } - mutex.lock(); - if (!cancelled.contains(runningJob)) - runningJob->postReply(errorCode, errorStr, readSize, t); - else - delete t; - mutex.unlock(); + case QQuickImageProvider::ImageResponse: + { + QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider); + QQuickImageResponse *response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize); + + QObject::connect(response, SIGNAL(finished()), threadObject, SLOT(asyncResponseFinished())); + + asyncResponses.insert(response, runningJob); + break; + } } } else { - QString lf = QQmlFile::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { + if (!localFile.isEmpty()) { // Image is local - load/decode immediately QImage image; QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; QString errorStr; - QFile f(lf); + QFile f(localFile); QSize readSize; if (f.open(QIODevice::ReadOnly)) { - if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize, autoTransform)) + if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, autoTransform)) errorCode = QQuickPixmapReply::Loading; } else { errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); @@ -671,7 +726,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u } mutex.lock(); if (!cancelled.contains(runningJob)) - runningJob->postReply(errorCode, errorStr, readSize, textureFactoryForImage(image)); + runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image)); mutex.unlock(); } else { // Network resource @@ -682,7 +737,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress); QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone); - replies.insert(reply, runningJob); + networkJobs.insert(reply, runningJob); } } } @@ -775,8 +830,6 @@ inline uint qHash(const QQuickPixmapKey &key) return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.autoTransform * 0x5c5c5c5c); } -class QSGContext; - class QQuickPixmapStore : public QObject { Q_OBJECT @@ -1084,7 +1137,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QImage image = provider->requestImage(imageId(url), &readSize, requestSize); if (!image.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault); } } case QQuickImageProvider::Pixmap: @@ -1092,9 +1145,14 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize); if (!pixmap.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault); } } + case QQuickImageProvider::ImageResponse: + { + // Fall through, ImageResponse providers never get here + Q_ASSERT(imageType != QQuickImageProvider::ImageResponse && "Sync call to ImageResponse provider"); + } } // provider has bad image type, or provider returned null image @@ -1115,7 +1173,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q AutoTransform appliedTransform = autoTransform; if (readImage(url, &f, &image, &errorString, &readSize, requestSize, appliedTransform)) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform); + return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform); } errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString()); @@ -1252,7 +1310,7 @@ void QQuickPixmap::setImage(const QImage &p) clear(); if (!p.isNull()) - d = new QQuickPixmapData(this, textureFactoryForImage(p)); + d = new QQuickPixmapData(this, QQuickTextureFactory::textureFactoryForImage(p)); } void QQuickPixmap::setPixmap(const QQuickPixmap &other) diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 6c333c6b13..707323f2e2 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -558,11 +558,7 @@ void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &val if (entry.name == name) { expressionIterator.remove(); if (state() && state()->isStateActive()) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name)); - if (oldBinding) { - QQmlPropertyPrivate::setBinding(d->property(name), 0); - oldBinding->destroy(); - } + QQmlPropertyPrivate::removeBinding(d->property(name), QQmlPropertyPrivate::DestroyOldBinding); d->property(name).write(value); } @@ -624,15 +620,9 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString if (entry.name == name) { entry.expression = expression; if (state() && state()->isStateActive()) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name)); - if (oldBinding) { - QQmlPropertyPrivate::setBinding(d->property(name), 0); - oldBinding->destroy(); - } - QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this)); newBinding->setTarget(d->property(name)); - QQmlPropertyPrivate::setBinding(d->property(name), newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); + QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); } return; } @@ -651,7 +641,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this)); newBinding->setTarget(d->property(name)); - QQmlPropertyPrivate::setBinding(d->property(name), newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); + QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); } else { QQuickStateAction action; action.restore = restoreEntryValues(); @@ -668,7 +658,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString action.toValue = newBinding->evaluate(); newBinding->destroy(); } else { - newBinding->setTarget(d->property(name)); + newBinding->setTarget(action.property); action.toBinding = QQmlAbstractBinding::getPointer(newBinding); action.deletableToBinding = true; @@ -677,7 +667,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString if (oldBinding) oldBinding->setEnabled(false, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); - QQmlPropertyPrivate::setBinding(action.property, newBinding, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); + QQmlPropertyPrivate::setBinding(newBinding, QQmlPropertyPrivate::None, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor); } } } diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp index 98d7a76c7e..483167f52d 100644 --- a/src/quick/util/qquickstate.cpp +++ b/src/quick/util/qquickstate.cpp @@ -361,7 +361,7 @@ void QQuickState::cancel() void QQuickStateAction::deleteFromBinding() { if (fromBinding) { - QQmlPropertyPrivate::setBinding(property, 0); + QQmlPropertyPrivate::removeBinding(property); fromBinding->destroy(); fromBinding = 0; } @@ -435,15 +435,11 @@ bool QQuickState::removeEntryFromRevertList(QObject *target, const QString &name while (revertListIterator.hasNext()) { QQuickSimpleAction &simpleAction = revertListIterator.next(); if (simpleAction.property().object() == target && simpleAction.property().name() == name) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property()); - if (oldBinding) { - QQmlPropertyPrivate::setBinding(simpleAction.property(), 0); - oldBinding->destroy(); - } + QQmlPropertyPrivate::removeBinding(simpleAction.property(), QQmlPropertyPrivate::DestroyOldBinding); simpleAction.property().write(simpleAction.value()); if (simpleAction.binding()) - QQmlPropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding()); + QQmlPropertyPrivate::setBinding(simpleAction.binding()); revertListIterator.remove(); return true; @@ -473,15 +469,11 @@ void QQuickState::removeAllEntriesFromRevertList(QObject *target) while (revertListIterator.hasNext()) { QQuickSimpleAction &simpleAction = revertListIterator.next(); if (simpleAction.property().object() == target) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property()); - if (oldBinding) { - QQmlPropertyPrivate::setBinding(simpleAction.property(), 0); - oldBinding->destroy(); - } + QQmlPropertyPrivate::removeBinding(simpleAction.property(), QQmlPropertyPrivate::DestroyOldBinding); simpleAction.property().write(simpleAction.value()); if (simpleAction.binding()) - QQmlPropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding()); + QQmlPropertyPrivate::setBinding(simpleAction.binding()); revertListIterator.remove(); } @@ -500,12 +492,8 @@ void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionL const QQuickStateAction &action = actionListIterator.next(); QQuickSimpleAction simpleAction(action); action.property.write(action.toValue); - if (!action.toBinding.isNull()) { - QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(simpleAction.property()); - if (oldBinding) - QQmlPropertyPrivate::setBinding(simpleAction.property(), 0); - QQmlPropertyPrivate::setBinding(simpleAction.property(), action.toBinding.data(), QQmlPropertyPrivate::DontRemoveBinding); - } + if (!action.toBinding.isNull()) + QQmlPropertyPrivate::setBinding(action.toBinding.data()); simpleActionList.append(simpleAction); } @@ -663,10 +651,7 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert) } if (!found) { QVariant cur = d->revertList.at(ii).property().read(); - QQmlAbstractBinding *delBinding = - QQmlPropertyPrivate::setBinding(d->revertList.at(ii).property(), 0); - if (delBinding) - delBinding->destroy(); + QQmlPropertyPrivate::removeBinding(d->revertList.at(ii).property(), QQmlPropertyPrivate::DestroyOldBinding); QQuickStateAction a; a.property = d->revertList.at(ii).property(); diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp index 74754a0bfb..88fc03bba8 100644 --- a/src/quick/util/qquicktimeline.cpp +++ b/src/quick/util/qquicktimeline.cpp @@ -659,7 +659,7 @@ void QQuickTimeLine::complete() */ void QQuickTimeLine::clear() { - for (QQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.begin(), cend = d->ops.end(); iter != cend; ++iter) + for (QQuickTimeLinePrivate::Ops::const_iterator iter = d->ops.cbegin(), cend = d->ops.cend(); iter != cend; ++iter) iter.key()->_t = 0; d->ops.clear(); d->length = 0; diff --git a/src/quick/util/qquicktransitionmanager.cpp b/src/quick/util/qquicktransitionmanager.cpp index 832596d9a2..ac57ac20a4 100644 --- a/src/quick/util/qquicktransitionmanager.cpp +++ b/src/quick/util/qquicktransitionmanager.cpp @@ -102,7 +102,7 @@ void QQuickTransitionManagerPrivate::applyBindings() { foreach(const QQuickStateAction &action, bindingsList) { if (!action.toBinding.isNull()) { - QQmlPropertyPrivate::setBinding(action.property, action.toBinding.data()); + QQmlPropertyPrivate::setBinding(action.toBinding.data()); } else if (action.event) { if (action.reverseEvent) action.event->reverse(); @@ -131,7 +131,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list, if (action.toBinding) d->bindingsList << action; if (action.fromBinding) - QQmlPropertyPrivate::setBinding(action.property, 0); // Disable current binding + QQmlPropertyPrivate::removeBinding(action.property); // Disable current binding if (action.event && action.event->changesBindings()) { //### assume isReversable()? d->bindingsList << action; action.event->clearBindings(); @@ -156,7 +156,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list, for (int ii = 0; ii < applyList.size(); ++ii) { const QQuickStateAction &action = applyList.at(ii); if (!action.toBinding.isNull()) { - QQmlPropertyPrivate::setBinding(action.property, action.toBinding.data(), QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); + QQmlPropertyPrivate::setBinding(action.toBinding.data(), QQmlPropertyPrivate::None, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); } else if (!action.event) { QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); } else if (action.event->isReversable()) { @@ -192,7 +192,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list, } if (action.toBinding) - QQmlPropertyPrivate::setBinding(action.property, 0); // Make sure this is disabled during the transition + QQmlPropertyPrivate::removeBinding(action.property); // Make sure this is disabled during the transition QQmlPropertyPrivate::write(action.property, action.fromValue, QQmlPropertyPrivate::BypassInterceptor | QQmlPropertyPrivate::DontRemoveBinding); } @@ -270,7 +270,7 @@ void QQuickTransitionManager::cancel() for(int i = 0; i < d->bindingsList.count(); ++i) { QQuickStateAction action = d->bindingsList[i]; if (!action.toBinding.isNull() && action.deletableToBinding) { - QQmlPropertyPrivate::setBinding(action.property, 0); + QQmlPropertyPrivate::removeBinding(action.property); action.toBinding.data()->destroy(); action.toBinding.clear(); action.deletableToBinding = false; diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp index 4d156a2d9a..4f6e49fa7a 100644 --- a/src/quick/util/qquickutilmodule.cpp +++ b/src/quick/util/qquickutilmodule.cpp @@ -49,6 +49,7 @@ #include "qquicktransition_p.h" #include "qquickanimator_p.h" #include "qquickshortcut_p.h" +#include "qquickvalidator_p.h" #include <qqmlinfo.h> #include <private/qqmltypenotavailable_p.h> #include <private/qquickanimationcontroller_p.h> @@ -87,6 +88,13 @@ void QQuickUtilModule::defineModule() qmlRegisterType<QQuickTransition>("QtQuick",2,0,"Transition"); qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation"); +#ifndef QT_NO_VALIDATOR + qmlRegisterType<QValidator>(); + qmlRegisterType<QQuickIntValidator>("QtQuick",2,0,"IntValidator"); + qmlRegisterType<QQuickDoubleValidator>("QtQuick",2,0,"DoubleValidator"); + qmlRegisterType<QRegExpValidator>("QtQuick",2,0,"RegExpValidator"); +#endif + qmlRegisterUncreatableType<QQuickAnimator>("QtQuick", 2, 2, "Animator", QQuickAbstractAnimation::tr("Animator is an abstract class")); qmlRegisterType<QQuickXAnimator>("QtQuick", 2, 2, "XAnimator"); qmlRegisterType<QQuickYAnimator>("QtQuick", 2, 2, "YAnimator"); diff --git a/src/quick/util/qquickvalidator.cpp b/src/quick/util/qquickvalidator.cpp new file mode 100644 index 0000000000..3eebf5d77a --- /dev/null +++ b/src/quick/util/qquickvalidator.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickvalidator_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_VALIDATOR + +/*! + \qmltype IntValidator + \instantiates QIntValidator + \inqmlmodule QtQuick + \ingroup qtquick-text-utility + \brief Defines a validator for integer values + + The IntValidator type provides a validator for integer values. + + If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to + interpret the number and will accept locale specific digits, group separators, and positive + and negative signs. In addition, IntValidator is always guaranteed to accept a number + formatted according to the "C" locale. +*/ + +QQuickIntValidator::QQuickIntValidator(QObject *parent) + : QIntValidator(parent) +{ +} + +/*! + \qmlproperty string QtQuick::IntValidator::locale + + This property holds the name of the locale used to interpret the number. + + \sa {QtQml::Qt::locale()}{Qt.locale()} +*/ + +QString QQuickIntValidator::localeName() const +{ + return locale().name(); +} + +void QQuickIntValidator::setLocaleName(const QString &name) +{ + if (locale().name() != name) { + setLocale(QLocale(name)); + emit localeNameChanged(); + } +} + +void QQuickIntValidator::resetLocaleName() +{ + QLocale defaultLocale; + if (locale() != defaultLocale) { + setLocale(defaultLocale); + emit localeNameChanged(); + } +} + +/*! + \qmlproperty int QtQuick::IntValidator::top + + This property holds the validator's highest acceptable value. + By default, this property's value is derived from the highest signed integer available (typically 2147483647). +*/ +/*! + \qmlproperty int QtQuick::IntValidator::bottom + + This property holds the validator's lowest acceptable value. + By default, this property's value is derived from the lowest signed integer available (typically -2147483647). +*/ + +/*! + \qmltype DoubleValidator + \instantiates QDoubleValidator + \inqmlmodule QtQuick + \ingroup qtquick-text-utility + \brief Defines a validator for non-integer numbers + + The DoubleValidator type provides a validator for non-integer numbers. + + Input is accepted if it contains a double that is within the valid range + and is in the correct format. + + Input is accepected but invalid if it contains a double that is outside + the range or is in the wrong format; e.g. with too many digits after the + decimal point or is empty. + + Input is rejected if it is not a double. + + Note: If the valid range consists of just positive doubles (e.g. 0.0 to + 100.0) and input is a negative double then it is rejected. If \l notation + is set to DoubleValidator.StandardNotation, and the input contains more + digits before the decimal point than a double in the valid range may have, + it is also rejected. If \l notation is DoubleValidator.ScientificNotation, + and the input is not in the valid range, it is accecpted but invalid. The + value may yet become valid by changing the exponent. +*/ + +QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent) + : QDoubleValidator(parent) +{ +} + +/*! + \qmlproperty string QtQuick::DoubleValidator::locale + + This property holds the name of the locale used to interpret the number. + + \sa {QtQml::Qt::locale()}{Qt.locale()} +*/ + +QString QQuickDoubleValidator::localeName() const +{ + return locale().name(); +} + +void QQuickDoubleValidator::setLocaleName(const QString &name) +{ + if (locale().name() != name) { + setLocale(QLocale(name)); + emit localeNameChanged(); + } +} + +void QQuickDoubleValidator::resetLocaleName() +{ + QLocale defaultLocale; + if (locale() != defaultLocale) { + setLocale(defaultLocale); + emit localeNameChanged(); + } +} + +/*! + \qmlproperty real QtQuick::DoubleValidator::top + + This property holds the validator's maximum acceptable value. + By default, this property contains a value of infinity. +*/ +/*! + \qmlproperty real QtQuick::DoubleValidator::bottom + + This property holds the validator's minimum acceptable value. + By default, this property contains a value of -infinity. +*/ +/*! + \qmlproperty int QtQuick::DoubleValidator::decimals + + This property holds the validator's maximum number of digits after the decimal point. + By default, this property contains a value of 1000. +*/ +/*! + \qmlproperty enumeration QtQuick::DoubleValidator::notation + This property holds the notation of how a string can describe a number. + + The possible values for this property are: + + \list + \li DoubleValidator.StandardNotation + \li DoubleValidator.ScientificNotation (default) + \endlist + + If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2). +*/ + +/*! + \qmltype RegExpValidator + \instantiates QRegExpValidator + \inqmlmodule QtQuick + \ingroup qtquick-text-utility + \brief Provides a string validator + + The RegExpValidator type provides a validator, which counts as valid any string which + matches a specified regular expression. +*/ +/*! + \qmlproperty regExp QtQuick::RegExpValidator::regExp + + This property holds the regular expression used for validation. + + Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression + matching "a". + + By default, this property contains a regular expression with the pattern .* that matches any string. +*/ + +#endif // QT_NO_VALIDATOR + +QT_END_NAMESPACE + diff --git a/src/quick/util/qquickvalidator_p.h b/src/quick/util/qquickvalidator_p.h new file mode 100644 index 0000000000..59d7884afc --- /dev/null +++ b/src/quick/util/qquickvalidator_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKVALIDATOR_P_H +#define QQUICKVALIDATOR_P_H + +#include <QtGui/qvalidator.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_VALIDATOR +class Q_AUTOTEST_EXPORT QQuickIntValidator : public QIntValidator +{ + Q_OBJECT + Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) +public: + QQuickIntValidator(QObject *parent = 0); + + QString localeName() const; + void setLocaleName(const QString &name); + void resetLocaleName(); + +Q_SIGNALS: + void localeNameChanged(); +}; + +class Q_AUTOTEST_EXPORT QQuickDoubleValidator : public QDoubleValidator +{ + Q_OBJECT + Q_PROPERTY(QString locale READ localeName WRITE setLocaleName RESET resetLocaleName NOTIFY localeNameChanged) +public: + QQuickDoubleValidator(QObject *parent = 0); + + QString localeName() const; + void setLocaleName(const QString &name); + void resetLocaleName(); + +Q_SIGNALS: + void localeNameChanged(); +}; +#endif + +QT_END_NAMESPACE + +#ifndef QT_NO_VALIDATOR +QML_DECLARE_TYPE(QValidator) +QML_DECLARE_TYPE(QQuickIntValidator) +QML_DECLARE_TYPE(QQuickDoubleValidator) +QML_DECLARE_TYPE(QRegExpValidator) +#endif + +#endif // QQUICKVALIDATOR_P_H diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri index 0e0df4e751..ffb31ae75e 100644 --- a/src/quick/util/util.pri +++ b/src/quick/util/util.pri @@ -29,7 +29,8 @@ SOURCES += \ $$PWD/qquickprofiler.cpp \ $$PWD/qquickfontmetrics.cpp \ $$PWD/qquicktextmetrics.cpp \ - $$PWD/qquickshortcut.cpp + $$PWD/qquickshortcut.cpp \ + $$PWD/qquickvalidator.cpp HEADERS += \ $$PWD/qquickapplication_p.h\ @@ -66,4 +67,5 @@ HEADERS += \ $$PWD/qquickprofiler_p.h \ $$PWD/qquickfontmetrics_p.h \ $$PWD/qquicktextmetrics_p.h \ - $$PWD/qquickshortcut_p.h + $$PWD/qquickshortcut_p.h \ + $$PWD/qquickvalidator_p.h diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 608c5f93f5..1afea402fd 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -531,6 +531,9 @@ QQuickWidget::Status QQuickWidget::status() const if (!d->component) return QQuickWidget::Null; + if (d->component->status() == QQmlComponent::Ready && !d->root) + return QQuickWidget::Error; + return QQuickWidget::Status(d->component->status()); } @@ -552,6 +555,10 @@ QList<QQmlError> QQuickWidget::errors() const QQmlError error; error.setDescription(QLatin1String("QQuickWidget: invalid qml engine.")); errs << error; + } else if (d->component->status() == QQmlComponent::Ready && !d->root) { + QQmlError error; + error.setDescription(QLatin1String("QQuickWidget: invalid root object.")); + errs << error; } return errs; @@ -871,14 +878,15 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj) if (QQuickItem *sgItem = qobject_cast<QQuickItem *>(obj)) { root = sgItem; sgItem->setParentItem(offscreenWindow->contentItem()); + } else if (qobject_cast<QWindow *>(obj)) { + qWarning() << "QQuickWidget does not support using windows as a root item." << endl + << endl + << "If you wish to create your root window from QML, consider using QQmlApplicationEngine instead." << endl; } else { qWarning() << "QQuickWidget only supports loading of root objects that derive from QQuickItem." << endl << endl - << "If your example is using QML 2, (such as qmlscene) and the .qml file you" << endl - << "loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur." << endl - << endl - << "To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the" << endl - << "QDeclarativeView class in the Qt Quick 1 module." << endl; + << "Ensure your QML code is written for QtQuick 2, and uses a root that is or" << endl + << "inherits from QtQuick's Item (not a Timer, QtObject, etc)." << endl; delete obj; root = 0; } |