From 06eaeb0ac8d861cf3e60b11a8fbbabdeef1d6759 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 1 Jul 2013 08:48:41 +0200 Subject: [PATCH] Get rid of the signal expression rewriter This replaces the entire rewriter with more or less: expressionToEval = "(function() { " + expr + " } )" This also fixes crashes at run-time when the signal rewriter was executed from the loader thread and tried to use a v4 identifier hash with the same engine that's also in the main thread. Change-Id: Ib1e4927d330706a593411fbff64ed3da1e23d0e0 Reviewed-by: Lars Knoll --- src/qml/debugger/qqmlenginedebugservice.cpp | 2 +- src/qml/qml/qml.pri | 2 - src/qml/qml/qqmlboundsignal.cpp | 161 ++++----- src/qml/qml/qqmlboundsignal_p.h | 18 +- src/qml/qml/qqmlcompiler.cpp | 30 +- src/qml/qml/qqmlcompiler_p.h | 1 - src/qml/qml/qqmlcustomparser.cpp | 9 - src/qml/qml/qqmlcustomparser_p.h | 1 - src/qml/qml/qqmlinstruction_p.h | 2 +- src/qml/qml/qqmlpropertycache.cpp | 55 --- src/qml/qml/qqmlpropertycache_p.h | 1 - src/qml/qml/qqmlrewrite.cpp | 369 --------------------- src/qml/qml/qqmlrewrite_p.h | 142 -------- src/qml/qml/qqmlvme.cpp | 6 +- src/qml/types/qqmlconnections.cpp | 6 +- src/quick/util/qquickpropertychanges.cpp | 2 +- .../tst_qqmlenginedebugservice.cpp | 2 +- tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 34 +- 18 files changed, 102 insertions(+), 741 deletions(-) delete mode 100644 src/qml/qml/qqmlrewrite.cpp delete mode 100644 src/qml/qml/qqmlrewrite_p.h diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 65f7419..2b01312 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -623,7 +623,7 @@ bool QQmlEngineDebugService::setBinding(int objectId, } else if (hasValidSignal(object, propertyName)) { QQmlBoundSignalExpression *qmlExpression = new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(property)->signalIndex(), QQmlContextData::get(context), object, expression.toString(), - false, filename, line, column); + filename, line, column); QQmlPropertyPrivate::takeSignalExpression(property, qmlExpression); } else if (property.isProperty()) { QQmlBinding *binding = new QQmlBinding(expression.toString(), object, QQmlContextData::get(context), filename, line, column);; diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 658b1f8..3a18d02 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -23,7 +23,6 @@ SOURCES += \ $$PWD/qqmlinfo.cpp \ $$PWD/qqmlerror.cpp \ $$PWD/qqmlscript.cpp \ - $$PWD/qqmlrewrite.cpp \ $$PWD/qqmlvaluetype.cpp \ $$PWD/qqmlaccessors.cpp \ $$PWD/qqmlxmlhttprequest.cpp \ @@ -95,7 +94,6 @@ HEADERS += \ $$PWD/qqmldata_p.h \ $$PWD/qqmlerror.h \ $$PWD/qqmlscript_p.h \ - $$PWD/qqmlrewrite_p.h \ $$PWD/qqmlvaluetype_p.h \ $$PWD/qqmlaccessors_p.h \ $$PWD/qqmlxmlhttprequest_p.h \ diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index e79aaef..80a06e9 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -50,7 +50,6 @@ #include "qqml.h" #include "qqmlcontext.h" #include "qqmlglobal_p.h" -#include "qqmlrewrite_p.h" #include #include #include "qqmlinfo.h" @@ -68,45 +67,21 @@ static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = { }; QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, - QQmlContextData *ctxt, QObject *scope, const QByteArray &expression, - bool isRewritten, const QString &fileName, quint16 line, quint16 column) - : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable), - m_fileName(fileName), - m_line(line), - m_column(column), - m_parameterCountForJS(-1), - m_target(target), - m_index(index), - m_expressionFunctionValid(false), - m_expressionFunctionRewritten(isRewritten), - m_invalidParameterName(false) -{ - init(ctxt, scope); - if (isRewritten) - m_expressionUtf8 = expression; - else - m_expression = QString::fromUtf8(expression); -} - -QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QString &expression, - bool isRewritten, const QString &fileName, quint16 line, quint16 column) + const QString &fileName, quint16 line, quint16 column, + const QString &handlerName) : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable), m_fileName(fileName), m_line(line), m_column(column), - m_parameterCountForJS(-1), m_target(target), m_index(index), m_expressionFunctionValid(false), - m_expressionFunctionRewritten(isRewritten), m_invalidParameterName(false) { init(ctxt, scope); - if (isRewritten) - m_expressionUtf8 = expression.toUtf8(); - else - m_expression = expression; + m_handlerName = handlerName; + m_expression = expression; } void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope) @@ -139,8 +114,6 @@ QString QQmlBoundSignalExpression::expression() const if (m_expressionFunctionValid) { Q_ASSERT (context() && engine()); return m_v8function.value().toQString(); - } else if (!m_expressionUtf8.isEmpty()) { - return QString::fromUtf8(m_expressionUtf8); } else { return m_expression; } @@ -164,47 +137,49 @@ void QQmlBoundSignalExpression::evaluate(void **a) //TODO: look at using the property cache here (as in the compiler) // for further optimization QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index); - QQmlRewrite::RewriteSignalHandler rewriter(ep->v4engine()); QString expression; - bool ok = true; - - if (m_expressionFunctionRewritten) { - expression = QString::fromUtf8(m_expressionUtf8); - - //if we need parameters, and the rewrite doesn't include them, - //create and insert the parameter string now - if (m_parameterCountForJS == -1 && signal.parameterCount()) { - const QString ¶meters = rewriter.createParameterString(signal.parameterNames(), - ep->v8engine()->illegalNames()); - int index = expression.indexOf(QLatin1Char('('), 1); - Q_ASSERT(index > -1); - expression.insert(index + 1, parameters); - setParameterCountForJS(rewriter.parameterCountForJS()); + expression = QStringLiteral("(function "); + expression += m_handlerName; + expression += QLatin1Char('('); + + QString error; + + bool unnamedParameter = false; + const QV4::IdentifierHash &illegalNames = ep->v8engine()->illegalNames(); + + const QList parameters = signal.parameterNames(); + for (int i = 0; i < parameters.count(); ++i) { + if (i > 0) + expression += QLatin1Char(','); + const QByteArray ¶m = parameters.at(i); + if (param.isEmpty()) + unnamedParameter = true; + else if (unnamedParameter) { + error = QCoreApplication::translate("QQmlRewrite", "Signal uses unnamed parameter followed by named parameter."); + break; + } else if (illegalNames.contains(param)) { + error = QCoreApplication::translate("QQmlRewrite", "Signal parameter \"%1\" hides global variable.").arg(QString::fromUtf8(param)); + break; } - - m_expressionUtf8.clear(); - } else { - //expression is still in its original form, so perform a full rewrite - expression = rewriter(m_expression, QString()/*no name hint available*/, &ok, - signal.parameterNames(), - ep->v8engine()->illegalNames()); - setParameterCountForJS(rewriter.parameterCountForJS()); - m_expression.clear(); + expression += QString::fromUtf8(param); } - if (rewriter.hasParameterError()) { - qmlInfo(scopeObject()) << rewriter.parameterError(); + if (!error.isEmpty()) { + qmlInfo(scopeObject()) << error; m_invalidParameterName = true; ep->dereferenceScarceResources(); return; } - if (ok) { - m_v8function = evalFunction(context(), scopeObject(), expression, - m_fileName, m_line, &m_v8qmlscope); - } + expression += QStringLiteral(") { "); + expression += m_expression; + expression += QStringLiteral(" })"); + m_expression.clear(); + + m_v8function = evalFunction(context(), scopeObject(), expression, + m_fileName, m_line, &m_v8qmlscope); if (m_v8function.isEmpty() || m_v8function.value().isNull()) { ep->dereferenceScarceResources(); @@ -214,42 +189,38 @@ void QQmlBoundSignalExpression::evaluate(void **a) m_expressionFunctionValid = true; } - if (!hasParameterInfo()) { - QQmlJavaScriptExpression::evaluate(context(), m_v8function.value(), 0); - } else { - QV8Engine *engine = ep->v8engine(); - QVarLengthArray dummy; - //TODO: lookup via signal index rather than method index as an optimization - int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex(); - int *argsTypes = QQmlPropertyCache::methodParameterTypes(m_target, methodIndex, dummy, 0); - int argCount = argsTypes ? m_parameterCountForJS : 0; - - QVarLengthArray args(argCount); - - for (int ii = 0; ii < argCount; ++ii) { - int type = argsTypes[ii + 1]; - //### ideally we would use metaTypeToJS, however it currently gives different results - // for several cases (such as QVariant type and QObject-derived types) - //args[ii] = engine->metaTypeToJS(type, a[ii + 1]); - if (type == QMetaType::QVariant) { - args[ii] = engine->fromVariant(*((QVariant *)a[ii + 1])); - } else if (type == QMetaType::Int) { - //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise - args[ii] = QV4::Value::fromInt32(*reinterpret_cast(a[ii + 1])); - } else if (type == qMetaTypeId()) { - args[ii] = reinterpret_cast(a[ii + 1])->toValue(); - } else if (ep->isQObject(type)) { - if (!*reinterpret_cast(a[ii + 1])) - args[ii] = QV4::Value::nullValue(); - else - args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast(a[ii + 1])); - } else { - args[ii] = engine->fromVariant(QVariant(type, a[ii + 1])); - } + QV8Engine *engine = ep->v8engine(); + QVarLengthArray dummy; + //TODO: lookup via signal index rather than method index as an optimization + int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex(); + int *argsTypes = QQmlPropertyCache::methodParameterTypes(m_target, methodIndex, dummy, 0); + int argCount = argsTypes ? *argsTypes : 0; + + QVarLengthArray args(argCount); + + for (int ii = 0; ii < argCount; ++ii) { + int type = argsTypes[ii + 1]; + //### ideally we would use metaTypeToJS, however it currently gives different results + // for several cases (such as QVariant type and QObject-derived types) + //args[ii] = engine->metaTypeToJS(type, a[ii + 1]); + if (type == QMetaType::QVariant) { + args[ii] = engine->fromVariant(*((QVariant *)a[ii + 1])); + } else if (type == QMetaType::Int) { + //### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise + args[ii] = QV4::Value::fromInt32(*reinterpret_cast(a[ii + 1])); + } else if (type == qMetaTypeId()) { + args[ii] = reinterpret_cast(a[ii + 1])->toValue(); + } else if (ep->isQObject(type)) { + if (!*reinterpret_cast(a[ii + 1])) + args[ii] = QV4::Value::nullValue(); + else + args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast(a[ii + 1])); + } else { + args[ii] = engine->fromVariant(QVariant(type, a[ii + 1])); } - - QQmlJavaScriptExpression::evaluate(context(), m_v8function.value(), argCount, args.data(), 0); } + + QQmlJavaScriptExpression::evaluate(context(), m_v8function.value(), argCount, args.data(), 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 33fa5be..7d3adb1 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -70,18 +70,15 @@ class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpres { public: QQmlBoundSignalExpression(QObject *target, int index, - QQmlContextData *ctxt, QObject *scope, const QByteArray &expression, - bool isRewritten, const QString &fileName, quint16 line, quint16 column); - QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QString &expression, - bool isRewritten, const QString &fileName, quint16 line, quint16 column); + const QString &fileName, quint16 line, quint16 column, + const QString &handlerName = QString()); + // "inherited" from QQmlJavaScriptExpression. static QString expressionIdentifier(QQmlJavaScriptExpression *); static void expressionChanged(QQmlJavaScriptExpression *); - void setParameterCountForJS(int count) { m_parameterCountForJS = count; } - // evaluation of a bound signal expression doesn't return any value void evaluate(void **a); @@ -97,27 +94,22 @@ private: ~QQmlBoundSignalExpression(); void init(QQmlContextData *ctxt, QObject *scope); - bool hasParameterInfo() const { return m_parameterCountForJS > 0; } QV4::PersistentValue m_v8qmlscope; QV4::PersistentValue m_v8function; - //either expressionUtf8 or expression will be used (but not both). - //once m_v8function is valid, we clear both expressions, and + QString m_handlerName; + //once m_v8function is valid, we clear expression and //extract it from m_v8function if needed. - QByteArray m_expressionUtf8; QString m_expression; //only used when expression needs to be rewritten QString m_fileName; quint16 m_line; quint16 m_column; - int m_parameterCountForJS; - QObject *m_target; int m_index; bool m_expressionFunctionValid:1; - bool m_expressionFunctionRewritten:1; bool m_invalidParameterName:1; }; diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index ee0d37b..a940bb2 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -53,10 +53,11 @@ #include "qqmlcontext_p.h" #include "qqmlcomponent_p.h" #include +#include +#include #include "qqmlvmemetaobject_p.h" #include "qqmlexpression_p.h" #include "qqmlproperty_p.h" -#include "qqmlrewrite_p.h" #include "qqmlscriptstring.h" #include "qqmlglobal_p.h" #include "qqmlbinding_p.h" @@ -1312,18 +1313,9 @@ void QQmlCompiler::genObjectBody(QQmlScript::Object *obj) } else if (v->type == Value::SignalExpression) { Instruction::StoreSignal store; + store.handlerName = output->indexForString(prop->name().toString()); store.signalIndex = prop->index; - - const QList ¶meterNameList = obj->metatype->signalParameterNames(prop->index); - QQmlRewrite::RewriteSignalHandler rewriter(enginePrivate->v4engine()); - int count = 0; - const QString &rewrite = rewriter(v->value.asAST(), v->value.asScript(), - prop->name().toString(), - obj->metatype->signalParameterStringForJS(prop->index, &count), - parameterNameList); - store.value = output->indexForByteArray(rewrite.toUtf8()); - store.parameterCount = - (rewriter.parameterAccess() == QQmlRewrite::RewriteSignalHandler::ParametersUnaccessed) ? 0 : count; + store.value = output->indexForString(v->value.asScript()); store.context = v->signalExpressionContextStack; store.line = v->location.start.line; store.column = v->location.start.column; @@ -1684,12 +1676,6 @@ bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *o //all handlers should be on the original, rather than cloned signals in order //to ensure all parameters are available (see qqmlboundsignal constructor for more details) prop->index = obj->metatype->originalClone(prop->index); - - QString errorString; - obj->metatype->signalParameterStringForJS(prop->index, 0, &errorString); - if (!errorString.isEmpty()) - COMPILE_EXCEPTION(prop, errorString); - prop->values.first()->signalExpressionContextStack = ctxt.stack; } } @@ -2626,12 +2612,6 @@ int QQmlCompiler::bindingIdentifier(const Variant &value) return output->indexForString(value.asScript()); } -QString QQmlCompiler::rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name) -{ - QQmlRewrite::RewriteSignalHandler rewriteSignalHandler(enginePrivate->v4engine()); - return rewriteSignalHandler(value.asAST(), value.asScript(), name); -} - // Ensures that the dynamic meta specification on obj is valid bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj) { @@ -2747,8 +2727,6 @@ bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj) return true; } -#include - static QStringList astNodeToStringList(QQmlJS::AST::Node *node) { if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) { diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 6a008a4..bc01335 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -295,7 +295,6 @@ public: int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType int bindingIdentifier(const QQmlScript::Variant& value); // for QQmlCustomParser::bindingIndex - QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler private: typedef QQmlCompiledData::Instruction Instruction; diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 3787c34..eba2e14 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -317,13 +317,4 @@ QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QQmlScript::Va return compiler->bindingIdentifier(value); } -/*! - Returns a rewritten \a handler. \a name - is used as the name of the rewritten function. -*/ -QString QQmlCustomParser::rewriteSignalHandler(const QQmlScript::Variant &value, const QString &name) -{ - return compiler->rewriteSignalHandler(value , name); -} - QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h index baf00ad..27f7e00 100644 --- a/src/qml/qml/qqmlcustomparser_p.h +++ b/src/qml/qml/qqmlcustomparser_p.h @@ -140,7 +140,6 @@ protected: const QMetaObject *resolveType(const QString&) const; QQmlBinding::Identifier bindingIdentifier(const QQmlScript::Variant&, const QString&); - QString rewriteSignalHandler(const QQmlScript::Variant&, const QString&); private: QList exceptions; diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h index 3be1857..a157a0b 100644 --- a/src/qml/qml/qqmlinstruction_p.h +++ b/src/qml/qml/qqmlinstruction_p.h @@ -392,9 +392,9 @@ union QQmlInstruction }; struct instr_storeSignal { QML_INSTR_HEADER + int handlerName; int signalIndex; int value; - int parameterCount; short context; ushort line; ushort column; diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 908ab27..903d50e 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -49,7 +49,6 @@ #include #include #include -#include #include @@ -1087,60 +1086,6 @@ QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int a return args; } -/*! \internal - \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()). - This is different from QMetaMethod::methodIndex(). -*/ -QString QQmlPropertyCache::signalParameterStringForJS(int index, int *count, QString *errorString) -{ - QQmlPropertyCache *c = 0; - QQmlPropertyData *signalData = signal(index, &c); - if (!signalData) - return QString(); - - typedef QQmlPropertyCacheMethodArguments A; - - if (signalData->arguments) { - A *arguments = static_cast(signalData->arguments); - if (arguments->signalParameterStringForJS) { - if (count) - *count = arguments->signalParameterCountForJS; - if (arguments->parameterError) { - if (errorString) - *errorString = *arguments->signalParameterStringForJS; - return QString(); - } - return *arguments->signalParameterStringForJS; - } - } - - QList parameterNameList = signalParameterNames(index); - - if (!signalData->arguments) { - A *args = c->createArgumentsObject(parameterNameList.count(), parameterNameList); - signalData->arguments = args; - } - - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - QQmlRewrite::RewriteSignalHandler rewriter(ep->v4engine()); - const QString ¶meters = rewriter.createParameterString(parameterNameList, - ep->v8engine()->illegalNames()); - - bool error = rewriter.hasParameterError(); - A *arguments = static_cast(signalData->arguments); - arguments->signalParameterStringForJS = new QString(error ? rewriter.parameterError() : parameters); - arguments->signalParameterCountForJS = rewriter.parameterCountForJS(); - if (count) - *count = arguments->signalParameterCountForJS; - if (error) { - arguments->parameterError = true; - if (errorString) - *errorString = *arguments->signalParameterStringForJS; - return QString(); - } - return *arguments->signalParameterStringForJS; -} - // Returns an array of the arguments for method \a index. The first entry in the array // is the number of arguments. int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index b7a9055..1f9199c 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -314,7 +314,6 @@ public: static int originalClone(QObject *, int index); QList signalParameterNames(int index) const; - QString signalParameterStringForJS(int index, int *count = 0, QString *errorString = 0); const char *className() const; diff --git a/src/qml/qml/qqmlrewrite.cpp b/src/qml/qml/qqmlrewrite.cpp deleted file mode 100644 index 7af447a..0000000 --- a/src/qml/qml/qqmlrewrite.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qqmlrewrite_p.h" - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP) - -namespace QQmlRewrite { - -static void rewriteStringLiteral(AST::StringLiteral *ast, const QString *code, int startPosition, TextWriter *writer) -{ - const unsigned position = ast->firstSourceLocation().begin() - startPosition + 1; - const unsigned length = ast->literalToken.length - 2; - const QStringRef spell = code->midRef(position, length); - const int end = spell.size(); - int index = 0; - - while (index < end) { - const QChar ch = spell.at(index++); - - if (index < end && ch == QLatin1Char('\\')) { - int pos = index; - - // skip a possibly empty sequence of \r characters - while (pos < end && spell.at(pos) == QLatin1Char('\r')) - ++pos; - - if (pos < end && spell.at(pos) == QLatin1Char('\n')) { - // This is a `\' followed by a newline terminator. - // In this case there's nothing to replace. We keep the code - // as it is and we resume the searching. - index = pos + 1; // refresh the index - } - } else if (ch == QLatin1Char('\r') || ch == QLatin1Char('\n')) { - const QString sep = ch == QLatin1Char('\r') ? QLatin1String("\\r") : QLatin1String("\\n"); - const int pos = index - 1; - QString s = sep; - - while (index < end && spell.at(index) == ch) { - s += sep; - ++index; - } - - writer->replace(position + pos, index - pos, s); - } - } -} - -SharedBindingTester::SharedBindingTester() -: _sharable(false), _safe(false) -{ -} - -void SharedBindingTester::parse(const QString &code) -{ - _sharable = _safe = false; - - Engine engine; - Lexer lexer(&engine); - Parser parser(&engine); - lexer.setCode(code, 0); - parser.parseStatement(); - if (!parser.statement()) - return; - - return parse(parser.statement()); -} - -void SharedBindingTester::parse(AST::Node *node) -{ - _sharable = true; - _safe = true; - - AST::Node::acceptChild(node, this); -} - -bool SharedBindingTester::visit(AST::FunctionDeclaration *) -{ - _sharable = false; - return false; -} - -bool SharedBindingTester::visit(AST::FunctionExpression *) -{ - _sharable = false; - return false; -} - -bool SharedBindingTester::visit(AST::CallExpression *e) -{ - static const QString mathString = QStringLiteral("Math"); - - if (AST::IdentifierExpression *ie = AST::cast(e->base)) { - if (ie->name == mathString) - return true; - } - - _safe = false; - return true; -} - -bool SharedBindingTester::visit(AST::IdentifierExpression *e) -{ - static const QString evalString = QStringLiteral("eval"); - if (e->name == evalString) - _sharable = false; - - return false; // IdentifierExpression is a leaf node anyway -} - -bool SharedBindingTester::visit(AST::PostDecrementExpression *) -{ - _safe = false; - return true; -} - -bool SharedBindingTester::visit(AST::PostIncrementExpression *) -{ - _safe = false; - return true; -} - -bool SharedBindingTester::visit(AST::PreDecrementExpression *) -{ - _safe = false; - return true; -} - -bool SharedBindingTester::visit(AST::PreIncrementExpression *) -{ - _safe = false; - return true; -} - -bool SharedBindingTester::visit(AST::BinaryExpression *e) -{ - if (e->op == QSOperator::InplaceAnd || - e->op == QSOperator::Assign || - e->op == QSOperator::InplaceSub || - e->op == QSOperator::InplaceDiv || - e->op == QSOperator::InplaceAdd || - e->op == QSOperator::InplaceLeftShift || - e->op == QSOperator::InplaceMod || - e->op == QSOperator::InplaceMul || - e->op == QSOperator::InplaceOr || - e->op == QSOperator::InplaceRightShift || - e->op == QSOperator::InplaceURightShift || - e->op == QSOperator::InplaceXor) - _safe = false; - - return true; -} - - -/* - RewriteSignalHandler performs two different types of rewrites, depending on what information - is available. - - When the target object is known, the rewriter can be provided a list of parameter names (and an - optional preconstructed parameter string), which allows us to: - 1. Check whether the parameters are used - 2. Rewrite with the parameters included in the rewrite - When this information is not available, we do a more generic rewrite, and rely on the expression - to perform a second rewrite with the parameter information (using createParameterString) - once the target object is known. -*/ -RewriteSignalHandler::RewriteSignalHandler(QV4::ExecutionEngine *engine) - : _writer(0) - , _code(0) - , _position(0) - , _parameterNames(engine) - , _parameterAccess(UnknownAccess) - , _parameterCountForJS(0) -{ -} - -void RewriteSignalHandler::accept(AST::Node *node) -{ - AST::Node::acceptChild(node, this); -} - -bool RewriteSignalHandler::visit(AST::StringLiteral *ast) -{ - rewriteStringLiteral(ast, _code, _position, _writer); - return false; -} - -//if we never make use of the signal parameters in our expression, -//there is no need to provide them -bool RewriteSignalHandler::visit(AST::IdentifierExpression *e) -{ - //optimization: don't need to compare strings if a parameter has already been marked as used. - if (_parameterAccess == ParametersAccessed) - return false; - - static const QString argumentsString = QStringLiteral("arguments"); - if (_parameterNames.contains(e->name.toString()) || e->name == argumentsString) - _parameterAccess = ParametersAccessed; - return false; -} - -static inline QString msgUnnamedErrorString() -{ - return QCoreApplication::translate("QQmlRewrite", "Signal uses unnamed parameter followed by named parameter."); -} - -static inline QString msgGlobalErrorString(const QString &p) -{ - return QCoreApplication::translate("QQmlRewrite", "Signal parameter \"%1\" hides global variable.").arg(p); -} - -#define EXIT_ON_ERROR(error) \ -{ \ - _error = error; \ - return QString(); \ -} - -//create a parameter string which can be inserted into a generic rewrite -QString RewriteSignalHandler::createParameterString(const QList ¶meterNameList, - const QV4::IdentifierHash &illegalNames) -{ - QString parameters; - bool unnamedParam = false; - for (int i = 0; i < parameterNameList.count(); ++i) { - QString param = QString::fromUtf8(parameterNameList.at(i)); - if (param.isEmpty()) - unnamedParam = true; - else if (unnamedParam) - EXIT_ON_ERROR(msgUnnamedErrorString()) - else if (illegalNames.contains(param)) - EXIT_ON_ERROR(msgGlobalErrorString(param)) - ++_parameterCountForJS; - parameters += param; - if (i < parameterNameList.count()-1) - parameters += QStringLiteral(","); - } - if (parameters.endsWith(QLatin1Char(','))) - parameters.resize(parameters.length() - 1); - return parameters; -} - -/* - If \a parameterString is provided, use \a parameterNameList to test whether the - parameters are used in the body of the function - * if unused, the rewrite will not include parameters, else - * if used, the rewrite will use \a parameterString - If \a parameterString is not provided, it is constructed from \a parameterNameList - as needed. -*/ -QString RewriteSignalHandler::operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name, - const QString ¶meterString, - const QList ¶meterNameList, - const QV4::IdentifierHash &illegalNames) -{ - if (rewriteDump()) { - qWarning() << "============================================================="; - qWarning() << "Rewrote:"; - qWarning() << qPrintable(code); - } - - bool hasParameterString = !parameterString.isEmpty(); - - QQmlJS::AST::ExpressionNode *expression = node->expressionCast(); - QQmlJS::AST::Statement *statement = node->statementCast(); - if (!expression && !statement) - return code; - - if (!parameterNameList.isEmpty()) { - for (int i = 0; i < parameterNameList.count(); ++i) { - QString param(QString::fromUtf8(parameterNameList.at(i).constData())); - _parameterNames.add(param, i); - if (!hasParameterString) - _parameterNameList.append(parameterNameList.at(i)); - } - - //this is set to Unaccessed here, and will be set to Accessed - //if we detect that a parameter has been used - _parameterAccess = ParametersUnaccessed; - } - - TextWriter w; - _writer = &w; - _code = &code; - - _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin(); - accept(node); - - QString rewritten = code; - w.write(&rewritten); - - QString parameters = (_parameterAccess == ParametersUnaccessed) ? QString() - : hasParameterString ? parameterString - : createParameterString(_parameterNameList, illegalNames); - rewritten = QStringLiteral("(function ") + name + QStringLiteral("(") + parameters + QStringLiteral(") { ") + rewritten + QStringLiteral(" })"); - - if (rewriteDump()) { - qWarning() << "To:"; - qWarning() << qPrintable(rewritten); - qWarning() << "============================================================="; - } - - return rewritten; -} - -QString RewriteSignalHandler::operator()(const QString &code, const QString &name, bool *ok, - const QList ¶meterNameList, - const QV4::IdentifierHash &illegalNames) -{ - Engine engine; - Lexer lexer(&engine); - Parser parser(&engine); - lexer.setCode(code, 0); - parser.parseStatement(); - if (!parser.statement()) { - if (ok) *ok = false; - return QString(); - } - if (ok) *ok = true; - return operator()(parser.statement(), code, name, QString(), parameterNameList, illegalNames); -} - -} // namespace QQmlRewrite - -QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlrewrite_p.h b/src/qml/qml/qqmlrewrite_p.h deleted file mode 100644 index 7cd283f..0000000 --- a/src/qml/qml/qqmlrewrite_p.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLREWRITE_P_H -#define QQMLREWRITE_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 -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace QQmlRewrite { -using namespace QQmlJS; - -class SharedBindingTester : protected AST::Visitor -{ - bool _sharable; - bool _safe; -public: - SharedBindingTester(); - - bool isSharable() const { return _sharable; } - bool isSafe() const { return isSharable() && _safe; } - - void parse(const QString &code); - void parse(AST::Node *Node); - - virtual bool visit(AST::FunctionDeclaration *); - virtual bool visit(AST::FunctionExpression *); - virtual bool visit(AST::IdentifierExpression *); - virtual bool visit(AST::CallExpression *); - virtual bool visit(AST::PostDecrementExpression *); - virtual bool visit(AST::PostIncrementExpression *); - virtual bool visit(AST::PreDecrementExpression *); - virtual bool visit(AST::PreIncrementExpression *); - virtual bool visit(AST::BinaryExpression *); -}; - -class RewriteSignalHandler: protected AST::Visitor -{ -public: - RewriteSignalHandler(QV4::ExecutionEngine *engine); - QString operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name, - const QString ¶meterString = QString(), - const QList ¶meterNameList = QList(), - const QV4::IdentifierHash &illegalNames = QV4::IdentifierHash()); - QString operator()(const QString &code, const QString &name, bool *ok = 0, - const QList ¶meterNameList = QList(), - const QV4::IdentifierHash &illegalNames = QV4::IdentifierHash()); - - enum ParameterAccess { - ParametersAccessed, - ParametersUnaccessed, - UnknownAccess - }; - - //returns the first n signal parameters that are used in the expression - int parameterCountForJS() const { return _parameterCountForJS; } - ParameterAccess parameterAccess() const { return _parameterAccess; } - QString createParameterString(const QList ¶meterNameList, - const QV4::IdentifierHash &illegalNames); - - bool hasParameterError() { return !_error.isEmpty(); } - QString parameterError() const { return _error; } - -protected: - void rewriteMultilineStrings(QString &code); - - using AST::Visitor::visit; - void accept(AST::Node *node); - virtual bool visit(AST::StringLiteral *ast); - virtual bool visit(AST::IdentifierExpression *); - -private: - TextWriter *_writer; - const QString *_code; - int _position; - QV4::IdentifierHash _parameterNames; - QList _parameterNameList; - ParameterAccess _parameterAccess; - int _parameterCountForJS; - QString _error; -}; - -} // namespace QQmlRewrite - -QT_END_NAMESPACE - -#endif // QQMLREWRITE_P_H - diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index cde16e8..f739079 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -757,9 +757,9 @@ QObject *QQmlVME::run(QList *errors, QQmlBoundSignal *bs = new QQmlBoundSignal(target, instr.signalIndex, target, engine); QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(target, instr.signalIndex, - CTXT, context, DATAS.at(instr.value), - true, COMP->name, instr.line, instr.column); - expr->setParameterCountForJS(instr.parameterCount); + CTXT, context, PRIMITIVES.at(instr.value), + COMP->name, instr.line, instr.column, + PRIMITIVES.at(instr.handlerName)); bs->takeExpression(expr); QML_END_INSTR(StoreSignal) diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 93df084..725c169 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -237,7 +237,7 @@ QQmlConnectionsParser::compile(const QList &props) QQmlScript::Variant v = qvariant_cast(value); if (v.isScript()) { ds << propName; - ds << rewriteSignalHandler(v, propName).toUtf8(); + ds << v.asScript(); ds << propLine; ds << propColumn; } else { @@ -270,7 +270,7 @@ void QQmlConnections::connectSignals() while (!ds.atEnd()) { QString propName; ds >> propName; - QByteArray script; + QString script; ds >> script; int line; ds >> line; @@ -295,7 +295,7 @@ void QQmlConnections::connectSignals() QQmlBoundSignalExpression *expression = ctxtdata ? new QQmlBoundSignalExpression(target(), signalIndex, ctxtdata, this, script, - true, location, line, column) : 0; + location, line, column) : 0; signal->takeExpression(expression); d->boundsignals += signal; } else { diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index ec3a2f8..b2aa004 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -343,7 +343,7 @@ void QQuickPropertyChangesPrivate::decode() handler->property = prop; handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(qmlContext(q)), object, expression, - false, url.toString(), line, column)); + url.toString(), line, column)); signalReplacements << handler; } else if (isScript) { // binding QString expression = data.toString(); diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index 421d4f0..11afc9e 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -969,7 +969,7 @@ void tst_QQmlEngineDebugService::setBindingForObject() QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered"); QCOMPARE(onEnteredRef.name, QString("onEntered")); - QCOMPARE(onEnteredRef.value, QVariant("(function onEntered() { { console.log('hello') } })")); + QCOMPARE(onEnteredRef.value, QVariant("{ console.log('hello') }")); m_dbg->setBindingForObject(mouseAreaObject.debugId, "onEntered", "{console.log('hello, world') }", false, diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index ff7d119..418e2ed 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -151,7 +151,7 @@ void tst_qqmlproperty::qmlmetaproperty() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(obj, QObjectPrivate::get(obj)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(obj, QObjectPrivate::get(obj)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -367,7 +367,7 @@ void tst_qqmlproperty::qmlmetaproperty_object() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -415,7 +415,7 @@ void tst_qqmlproperty::qmlmetaproperty_object() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -470,7 +470,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -518,7 +518,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -568,7 +568,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -617,7 +617,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -671,7 +671,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -719,7 +719,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -774,7 +774,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&object, QObjectPrivate::get(&object)->signalIndex("destroyed()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -822,7 +822,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QObjectPrivate::get(&dobject)->signalIndex("clicked()"), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -872,7 +872,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -921,7 +921,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); - QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1); + QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(&dobject, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1); QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr); QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted()); @@ -1103,7 +1103,7 @@ void tst_qqmlproperty::read() QQmlProperty p(&o, "onClicked"); QCOMPARE(p.read(), QVariant()); - QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1))); + QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1))); QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p)); QCOMPARE(p.read(), QVariant()); @@ -1115,7 +1115,7 @@ void tst_qqmlproperty::read() QQmlProperty p(&o, "onPropertyWithNotifyChanged"); QCOMPARE(p.read(), QVariant()); - QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1))); + QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1))); QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p)); QCOMPARE(p.read(), QVariant()); @@ -1271,7 +1271,7 @@ void tst_qqmlproperty::write() QQmlProperty p(&o, "onClicked"); QCOMPARE(p.write(QVariant("console.log(1921)")), false); - QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1))); + QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1))); QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p)); QCOMPARE(p.write(QVariant("console.log(1921)")), false); @@ -1285,7 +1285,7 @@ void tst_qqmlproperty::write() QQmlProperty p(&o, "onPropertyWithNotifyChanged"); QCOMPARE(p.write(QVariant("console.log(1921)")), false); - QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1))); + QVERIFY(0 == QQmlPropertyPrivate::takeSignalExpression(p, new QQmlBoundSignalExpression(&o, QQmlPropertyPrivate::get(p)->signalIndex(), QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), QString(), -1, -1))); QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p)); QCOMPARE(p.write(QVariant("console.log(1921)")), false); -- 2.7.4