Fix use of function expressions with signal handlers
Writing onClicked: function(mouseEvent) { ... } would get silently "accepted" by the engine, but it wouldn't do anything. We basically wrapped it in a new function, so that it became onClicked: function(mouse){ function(mouseEvent() {} } which is a noop. With older versions this used to produce a syntax error. However the better fix is to simply support this kind of assignment for more expressive signal handlers, because now the names of the signal parameters can be explicitly named (with names of your choice). Change-Id: I96369f8805fab97509784222f614ee17cf681aba Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> Reviewed-by: Michael Brasser <michael.brasser@live.com>
This commit is contained in:
parent
45ea8df187
commit
c907eb1b5b
|
@ -1046,16 +1046,29 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
|
|||
paramList = paramList->finish();
|
||||
|
||||
QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex);
|
||||
QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(foe->node);
|
||||
QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement);
|
||||
QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement);
|
||||
elements = elements->finish();
|
||||
QQmlJS::AST::FunctionDeclaration *functionDeclaration = 0;
|
||||
if (QQmlJS::AST::ExpressionStatement *es = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(foe->node)) {
|
||||
if (QQmlJS::AST::FunctionExpression *fe = QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression*>(es->expression)) {
|
||||
functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(fe->name, fe->formals, fe->body);
|
||||
functionDeclaration->functionToken = fe->functionToken;
|
||||
functionDeclaration->identifierToken = fe->identifierToken;
|
||||
functionDeclaration->lparenToken = fe->lparenToken;
|
||||
functionDeclaration->rparenToken = fe->rparenToken;
|
||||
functionDeclaration->lbraceToken = fe->lbraceToken;
|
||||
functionDeclaration->rbraceToken = fe->rbraceToken;
|
||||
}
|
||||
}
|
||||
if (!functionDeclaration) {
|
||||
QQmlJS::AST::Statement *statement = static_cast<QQmlJS::AST::Statement*>(foe->node);
|
||||
QQmlJS::AST::SourceElement *sourceElement = new (pool) QQmlJS::AST::StatementSourceElement(statement);
|
||||
QQmlJS::AST::SourceElements *elements = new (pool) QQmlJS::AST::SourceElements(sourceElement);
|
||||
elements = elements->finish();
|
||||
|
||||
QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements);
|
||||
|
||||
QQmlJS::AST::FunctionDeclaration *functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body);
|
||||
functionDeclaration->functionToken = foe->node->firstSourceLocation();
|
||||
QQmlJS::AST::FunctionBody *body = new (pool) QQmlJS::AST::FunctionBody(elements);
|
||||
|
||||
functionDeclaration = new (pool) QQmlJS::AST::FunctionDeclaration(compiler->newStringRef(stringAt(binding->propertyNameIndex)), paramList, body);
|
||||
functionDeclaration->functionToken = foe->node->firstSourceLocation();
|
||||
}
|
||||
foe->node = functionDeclaration;
|
||||
binding->propertyNameIndex = compiler->registerString(propertyName);
|
||||
binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerExpression;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import Test 1.0
|
||||
MyQmlObject {
|
||||
onBasicSignal: function() { basicSlot() }
|
||||
onBasicParameterizedSignal: function(param) { basicSlotWithArgs(param) }
|
||||
}
|
|
@ -117,6 +117,7 @@ private slots:
|
|||
void idProperty();
|
||||
void autoNotifyConnection();
|
||||
void assignSignal();
|
||||
void assignSignalFunctionExpression();
|
||||
void overrideSignal_data();
|
||||
void overrideSignal();
|
||||
void dynamicProperties();
|
||||
|
@ -1263,6 +1264,17 @@ void tst_qqmllanguage::assignSignal()
|
|||
emit object->basicParameterizedSignal(9);
|
||||
}
|
||||
|
||||
void tst_qqmllanguage::assignSignalFunctionExpression()
|
||||
{
|
||||
QQmlComponent component(&engine, testFileUrl("assignSignalFunctionExpression.qml"));
|
||||
VERIFY_ERRORS(0);
|
||||
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
|
||||
QVERIFY(object != 0);
|
||||
QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
|
||||
emit object->basicSignal();
|
||||
QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
|
||||
emit object->basicParameterizedSignal(9);
|
||||
}
|
||||
|
||||
void tst_qqmllanguage::overrideSignal_data()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue