diff options
4 files changed, 32 insertions, 0 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 9605eda030..b7295626ae 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1984,6 +1984,12 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings( scan.enterEnvironment(f.parentNode, QV4::Compiler::ContextType::Binding, qmlName(f)); } + /* We do not want to visit the whole function, as we already called enterQmlFunction + However, there might be a function defined as a default argument of the function. + That needs to be considered, too, so we call handleTopLevelFunctionFormals to + deal with them. + */ + scan.handleTopLevelFunctionFormals(function); scan(function ? function->body : f.node); scan.leaveEnvironment(); } diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index 073ee5c2a4..d2868fc428 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -83,6 +83,13 @@ public: ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType); void operator()(QQmlJS::AST::Node *node); + // see comment at its call site in generateJSCodeForFunctionsAndBindings + // for why this function is necessary + void handleTopLevelFunctionFormals(QQmlJS::AST::FunctionExpression *node) { + if (node && node->formals) + node->formals->accept(this); + } + void enterGlobalEnvironment(ContextType compilationMode); void enterEnvironment(QQmlJS::AST::Node *node, ContextType compilationMode, const QString &name); diff --git a/tests/auto/qml/qqmlecmascript/data/functionAsDefaultArgument.qml b/tests/auto/qml/qqmlecmascript/data/functionAsDefaultArgument.qml new file mode 100644 index 0000000000..9f576d1af8 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/functionAsDefaultArgument.qml @@ -0,0 +1,8 @@ +import QtQml 2.15 + +QtObject { + id: root + + function f(inner=function(){ root.objectName = "didRun" } ){ inner() } + Component.onCompleted: f() +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index ad47c232f5..0e3988e01f 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -427,6 +427,7 @@ private slots: void asCast(); void functionNameInFunctionScope(); + void functionAsDefaultArgument(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -10061,6 +10062,16 @@ void tst_qqmlecmascript::functionNameInFunctionScope() QVERIFY(m2.property("c").isCallable()); } + +void tst_qqmlecmascript::functionAsDefaultArgument() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("functionAsDefaultArgument.qml")); + QScopedPointer root(component.create()); + QVERIFY(root); + QCOMPARE(root->objectName(), "didRun"); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" |