Correctly check for duplicate parameter names

Those are not allowed as soon as we have default values for parameters
or rest arguments.

Change-Id: I7dec826c37e6045e4dd1f6b0adb90301efe33daf
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Lars Knoll 2018-02-10 19:17:40 +01:00
parent 219485d898
commit 31026b2e83
6 changed files with 29 additions and 13 deletions

View File

@ -1824,6 +1824,9 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
}
scan.leaveEnvironment();
if (hasError)
return QVector<int>();
_context = nullptr;
for (int i = 0; i < functions.count(); ++i) {

View File

@ -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 {

View File

@ -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

View File

@ -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<CompiledData::CompilationUnit> compilationUnit = cg.generateCompilationUnit();
Function *vmf = compilationUnit->linkToEngine(scope.engine);

View File

@ -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);
}

View File

@ -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