diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-01-14 12:00:56 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-01-16 12:46:52 +0100 |
commit | 291aea14636a0e779d874a01630524facb1397dd (patch) | |
tree | 044ff4131a9b3f5a3edb00e6a807d0609c04a182 /src/qml | |
parent | 39f1e0d66dc434e764731fbfed29c8fd98d217aa (diff) | |
parent | 88e87647c3b7d651dba2c8e61f945d47ecdd02c4 (diff) |
Merge remote-tracking branch 'origin/5.4' into dev
Conflicts:
.qmake.conf
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4debugging.cpp
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/quick/scenegraph/shaders/visualization.frag
tests/auto/qml/qjsengine/tst_qjsengine.cpp
Change-Id: I492e8546c278f80a300a2129e9a29d861e144a30
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 26 | ||||
-rw-r--r-- | src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml | 1 | ||||
-rw-r--r-- | src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml | 1 | ||||
-rw-r--r-- | src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml | 1 | ||||
-rw-r--r-- | src/qml/doc/src/cppintegration/definetypes.qdoc | 46 | ||||
-rw-r--r-- | src/qml/doc/src/qmlfunctions.qdoc | 24 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4dateobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4debugging.cpp | 18 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 14 |
14 files changed, 144 insertions, 40 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index c2d123c96f..84e6c76cc4 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1138,7 +1138,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, if (!prop->isWritable() && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration)) COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property").arg(stringAt(binding->propertyNameIndex))); - Q_ASSERT(binding->type = QV4::CompiledData::Binding::Type_Script); + Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script); const QString string = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); if (!string.constData()->isUpper()) return true; diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index d89ea07087..c0a14a5c80 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -2543,17 +2543,21 @@ public: } else if (m->source->asConvert()) { break; } else if (Binop *b = m->source->asBinop()) { + bool iterateOnOperands = true; + switch (b->op) { + case OpSub: + case OpMul: case OpAdd: - if (b->left->type & NumberType || b->right->type & NumberType) + if (b->left->type == SInt32Type && b->right->type == SInt32Type) { + iterateOnOperands = false; break; - else + } else { continue; + } case OpBitAnd: case OpBitOr: case OpBitXor: - case OpSub: - case OpMul: case OpLShift: case OpRShift: case OpURShift: @@ -2561,10 +2565,13 @@ public: default: continue; } - if (Temp *lt = b->left->asTemp()) - candidates.append(*lt); - if (Temp *rt = b->right->asTemp()) - candidates.append(*rt); + + if (iterateOnOperands) { + if (Temp *lt = b->left->asTemp()) + candidates.append(*lt); + if (Temp *rt = b->right->asTemp()) + candidates.append(*rt); + } } else if (Unop *u = m->source->asUnop()) { if (u->op == OpCompl || u->op == OpUPlus) { if (Temp *t = u->expr->asTemp()) @@ -4033,8 +4040,7 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df) default: break; } - if (casted) { - Q_ASSERT(casted->type == SInt32Type); + if (casted && casted->type == SInt32Type) { m->source = casted; W += m; continue; diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml index 8f628232c1..c161a10610 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml @@ -58,7 +58,6 @@ Rectangle { } Button { id: quitButton - // change the button label to the active state id text: "quit" } } diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml index bf84b4cc90..5bbd9ca9df 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml @@ -53,7 +53,6 @@ Rectangle { } Button { id: quitButton - // change the button label to the active state id text: "quit" } } diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml index dfa093716f..932a9249d3 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml @@ -54,7 +54,6 @@ Rectangle { } Button { id: quitButton - // change the button label to the active state id text: "quit" } } diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index 03607df2e5..2f780503b2 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -294,6 +294,52 @@ This is useful when deriving from base classes provided by other authors, e.g. when extending classes from the Qt Quick module. +\section2 Registering Extension Objects + +When integrating existing classes and technology into QML, APIs will +often need tweaking to fit better into the declarative environment. +Although the best results are usually obtained by modifying the original +classes directly, if this is either not possible or is complicated by some +other concerns, extension objects allow limited extension possibilities +without direct modifications. + +\e{Extension objects} add additional properties to an existing type. Extension +objects can only add properties, not signals or methods. An extended type +definition allows the programmer to supply an additional type, known as the +\e{extension type}, when registering the class. The properties are transparently +merged with the original target class when used from within QML. For example: + +\snippet referenceexamples/extended/example.qml 0 + +The \c leftMargin property is a new property added to an existing C++ type, \l +QLineEdit, without modifying its source code. + +The \l qmlRegisterExtendedType() function is for registering extended types. +Note that it has two forms. + +\code +template<typename T, typename ExtendedT> +int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) + +template<typename T, typename ExtendedT> +int qmlRegisterExtendedType() +\endcode + +This functions should be used instead of the regular \c qmlRegisterType() +variations. The arguments are identical to the corresponding non-extension +registration functions, except for the ExtendedT parameter which is the type of +the extension object. + +An extension class is a regular QObject, with a constructor that takes a QObject +pointer. However, the extension class creation is delayed until the first +extended property is accessed. The extension class is created and the target +object is passed in as the parent. When the property on the original is +accessed, the corresponding property on the extension object is used instead. + +The \l{Extending QML - Extension Objects Example}{Extension Objects Example} +demonstrates a usage of extension objects. + + \section1 Defining QML-Specific Types and Attributes diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index e95784dc5c..108b99277f 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -157,8 +157,25 @@ */ /*! - \fn int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message) - \relates QQmlEgine + \fn int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) + \relates QQmlEngine + + This template function registers the C++ type and its extension object in the + QML system with the name \a qmlName in the library imported from \a uri having + version number composed from \a versionMajor and \a versionMinor. Properties + not available in the main type will be searched for in the extension object. + + Returns the QML type id. + + #include <QtQml> to use this function. + + \sa qmlRegisterType(), {Registering Extension Objects} +*/ + + +/*! + \fn int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) + \relates QQmlEngine This template function registers the C++ type and its extension in the QML system with the name \a qmlName in the library imported @@ -180,7 +197,8 @@ /*! \fn int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, QQmlCustomParser *parser) - \relates QQmlEgine + \relates QQmlEngine + \internal This template function registers the C++ type and its extension in the QML system with the name \a qmlName in the library imported diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 85bcadd8d2..40c02ef4ee 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -475,3 +475,19 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object ** ScopedValue n(scope, name); return engine()->throwReferenceError(n); } + +Heap::FunctionObject *ExecutionContext::getFunctionObject() const +{ + Scope scope(d()->engine); + ScopedContext it(scope, this->d()); + for (; it; it = it->d()->parent) { + if (const CallContext *callCtx = it->asCallContext()) + return callCtx->d()->function; + else if (it->asCatchContext() || it->asWithContext()) + continue; // look in the parent context for a FunctionObject + else + break; + } + + return 0; +} diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index ea2d266146..48319c7444 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -154,6 +154,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed inline CallContext *asCallContext(); inline const CallContext *asCallContext() const; + inline const CatchContext *asCatchContext() const; + inline const WithContext *asWithContext() const; + + Heap::FunctionObject *getFunctionObject() const; static void markObjects(Heap::Base *m, ExecutionEngine *e); }; @@ -202,6 +206,16 @@ inline const CallContext *ExecutionContext::asCallContext() const return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0; } +inline const CatchContext *ExecutionContext::asCatchContext() const +{ + return d()->type == Heap::ExecutionContext::Type_CatchContext ? static_cast<const CatchContext *>(this) : 0; +} + +inline const WithContext *ExecutionContext::asWithContext() const +{ + return d()->type == Heap::ExecutionContext::Type_WithContext ? static_cast<const WithContext *>(this) : 0; +} + /* Function *f, int argc */ #define requiredMemoryForExecutionContect(f, argc) \ ((sizeof(CallContext::Data) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData) diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 7f79de3035..4379e3ff94 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -482,6 +482,8 @@ static inline double ParseString(const QString &s) QDateTime dt = QDateTime::fromString(s, Qt::TextDate); if (!dt.isValid()) dt = QDateTime::fromString(s, Qt::ISODate); + if (!dt.isValid()) + dt = QDateTime::fromString(s, Qt::RFC2822Date); if (!dt.isValid()) { QStringList formats; formats << QStringLiteral("M/d/yyyy") diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 9361fa1a23..01ee9585c3 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -523,7 +523,6 @@ void Debugger::maybeBreakAtInstruction() return; QMutexLocker locker(&m_lock); - int lineNumber = engine()->currentContext()->lineNumber; if (m_gatherSources) { m_gatherSources->run(); @@ -547,8 +546,12 @@ void Debugger::maybeBreakAtInstruction() if (m_pauseRequested) { // Serve debugging requests from the agent m_pauseRequested = false; pauseAndWait(PauseRequest); - } else if (m_haveBreakPoints && reallyHitTheBreakPoint(getFunction()->sourceFile(), lineNumber)) { - pauseAndWait(BreakPoint); + } else if (m_haveBreakPoints) { + if (Function *f = getFunction()) { + const int lineNumber = engine()->currentContext()->lineNumber; + if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber)) + pauseAndWait(BreakPoint); + } } } @@ -594,12 +597,11 @@ Function *Debugger::getFunction() const { Scope scope(m_engine); ScopedContext context(scope, m_engine->currentContext()); - if (CallContext *callCtx = context->asCallContext()) - return callCtx->d()->function->function; - else { - Q_ASSERT(context->d()->type == QV4::Heap::ExecutionContext::Type_GlobalContext); + ScopedFunctionObject function(scope, context->getFunctionObject()); + if (function) + return function->function(); + else return context->d()->engine->globalCode; - } } void Debugger::pauseAndWait(PauseReason reason) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 4f8f329e2b..a51ea36351 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -762,21 +762,21 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const QVector<StackFrame> stack; ScopedContext c(scope, currentContext()); + ScopedFunctionObject function(scope); while (c && frameLimit) { - CallContext *callCtx = c->asCallContext(); - if (callCtx && callCtx->d()->function) { + function = c->getFunctionObject(); + if (function) { StackFrame frame; - ScopedFunctionObject function(scope, callCtx->d()->function); - if (function->function()) - frame.source = function->function()->sourceFile(); + if (const Function *f = function->function()) + frame.source = f->sourceFile(); name = function->name(); frame.function = name->toQString(); frame.line = -1; frame.column = -1; - if (callCtx->d()->function->function) + if (function->function()) // line numbers can be negative for places where you can't set a real breakpoint - frame.line = qAbs(callCtx->d()->lineNumber); + frame.line = qAbs(c->d()->lineNumber); stack.append(frame); --frameLimit; @@ -791,7 +791,6 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const frame.line = rootContext()->lineNumber; frame.column = -1; - stack.append(frame); } return stack; diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 61cd53cd61..687ff19be4 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -69,9 +69,9 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } // // NOTE: This should match the logic in qv4targetplatform_p.h! -#if defined(Q_PROCESSOR_X86) && (defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD)) +#if defined(Q_PROCESSOR_X86) && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD)) #define V4_ENABLE_JIT -#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)) +#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)) #define V4_ENABLE_JIT #elif defined(Q_PROCESSOR_ARM_32) diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 7ec66dd0e5..1248991789 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -814,13 +814,17 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase f->call(callData); if (scope.hasException()) { + QQmlError error = v4->catchExceptionAsQmlError(); + if (error.description().isEmpty()) { + QV4::ScopedString name(scope, f->name()); + error.setDescription(QString::fromLatin1("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString())); + } if (QQmlEngine *qmlEngine = v4->qmlEngine()) { - QQmlError error = v4->catchExceptionAsQmlError(); - if (error.description().isEmpty()) { - QV4::ScopedString name(scope, f->name()); - error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(name->toQString())); - } QQmlEnginePrivate::get(qmlEngine)->warning(error); + } else { + QMessageLogger(error.url().toString().toLatin1().constData(), + error.line(), 0).warning().noquote() + << error.toString(); } } } |