diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 4a1b27d7aa..4e87c96b68 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1824,6 +1824,9 @@ QVector JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList(); + _context = nullptr; for (int i = 0; i < functions.count(); ++i) { diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 52dd32dcc5..b891b5bbad 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -120,6 +120,9 @@ void Codegen::generateFromProgram(const QString &fileName, ScanFunctions scan(this, sourceCode, mode); scan(node); + if (hasError) + return; + defineFunction(QStringLiteral("%entry"), node, nullptr, node->elements); } @@ -2210,16 +2213,6 @@ static bool endsWithReturn(Node *node) return false; } -static bool isSimpleParameterList(AST::FormalParameterList *formals) -{ - while (formals) { - if (formals->isRest || formals->defaultExpression) - return false; - formals = formals->next; - } - return true; -} - int Codegen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::SourceElements *body) @@ -2324,7 +2317,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, } } if (_context->usesArgumentsObject == Context::ArgumentsObjectUsed) { - if (_context->isStrict || !isSimpleParameterList(formals)) { + if (_context->isStrict || !formals->isSimpleParameterList()) { Instruction::CreateUnmappedArgumentsObject setup; bytecodeGenerator->addInstruction(setup); } else { diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index f985c74f9d..8824a47def 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -431,12 +431,14 @@ void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete if (body && !_context->isStrict) checkDirectivePrologue(body->elements); + bool isSimpleParameterList = formals->isSimpleParameterList(); + for (FormalParameterList *it = formals; it; it = it->next) { QString arg = it->name.toString(); int duplicateIndex = _context->arguments.indexOf(arg); if (duplicateIndex != -1) { - if (_context->isStrict) { - _cg->throwSyntaxError(it->identifierToken, QStringLiteral("Duplicate parameter name '%1' is not allowed in strict mode").arg(arg)); + if (_context->isStrict || !isSimpleParameterList) { + _cg->throwSyntaxError(it->identifierToken, QStringLiteral("Duplicate parameter name '%1' is not allowed.").arg(arg)); return; } else { // change the name of the earlier argument to enforce the specified lookup semantics diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 73a8eb1193..390e0d5161 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -240,6 +240,9 @@ ReturnedValue FunctionCtor::callAsConstructor(const FunctionObject *f, const Val RuntimeCodegen cg(scope.engine, &jsGenerator, false); cg.generateFromFunctionExpression(QString(), function, fe, &module); + if (scope.hasException()) + return Encode::undefined(); + QQmlRefPointer compilationUnit = cg.generateCompilationUnit(); Function *vmf = compilationUnit->linkToEngine(scope.engine); diff --git a/src/qml/jsruntime/qv4runtimecodegen.cpp b/src/qml/jsruntime/qv4runtimecodegen.cpp index fe18ddf9ed..8080ef7344 100644 --- a/src/qml/jsruntime/qv4runtimecodegen.cpp +++ b/src/qml/jsruntime/qv4runtimecodegen.cpp @@ -58,6 +58,9 @@ void RuntimeCodegen::generateFromFunctionExpression(const QString &fileName, scan(ast); scan.leaveEnvironment(); + if (hasError) + return; + int index = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : nullptr); _module->rootContext = _module->functions.at(index); } diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 61ee89ad2f..51f3d78588 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -2099,6 +2099,18 @@ public: return n; } + bool isSimpleParameterList() + { + AST::FormalParameterList *formals = this; + while (formals) { + if (formals->isRest || formals->defaultExpression) + return false; + formals = formals->next; + } + return true; + } + + void accept0(Visitor *visitor) override; SourceLocation firstSourceLocation() const override