aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compilerscanfunctions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp')
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp114
1 files changed, 56 insertions, 58 deletions
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 84ee452332..3f7211b95e 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -95,25 +95,23 @@ void ScanFunctions::leaveEnvironment()
_context = _contextStack.isEmpty() ? 0 : _contextStack.top();
}
-void ScanFunctions::checkDirectivePrologue(SourceElements *ast)
+void ScanFunctions::checkDirectivePrologue(StatementList *ast)
{
- for (SourceElements *it = ast; it; it = it->next) {
- if (StatementSourceElement *stmt = cast<StatementSourceElement *>(it->element)) {
- if (ExpressionStatement *expr = cast<ExpressionStatement *>(stmt->statement)) {
- if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
- // Use the source code, because the StringLiteral's
- // value might have escape sequences in it, which is not
- // allowed.
- if (strLit->literalToken.length < 2)
- continue;
- QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
- if (str == QLatin1String("use strict")) {
- _context->isStrict = true;
- } else {
- // TODO: give a warning.
- }
+ for (StatementList *it = ast; it; it = it->next) {
+ if (ExpressionStatement *expr = cast<ExpressionStatement *>(it->statement)) {
+ if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) {
+ // Use the source code, because the StringLiteral's
+ // value might have escape sequences in it, which is not
+ // allowed.
+ if (strLit->literalToken.length < 2)
continue;
+ QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2);
+ if (str == QLatin1String("use strict")) {
+ _context->isStrict = true;
+ } else {
+ // TODO: give a warning.
}
+ continue;
}
}
@@ -138,20 +136,10 @@ void ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc)
}
}
-bool ScanFunctions::formalsContainName(AST::FormalParameterList *parameters, const QString &name)
-{
- while (parameters) {
- if (parameters->name == name)
- return true;
- parameters = parameters->next;
- }
- return false;
-}
-
bool ScanFunctions::visit(Program *ast)
{
enterEnvironment(ast, defaultProgramMode);
- checkDirectivePrologue(ast->elements);
+ checkDirectivePrologue(ast->statements);
return true;
}
@@ -237,7 +225,8 @@ bool ScanFunctions::visit(ExpressionStatement *ast)
if (!_allowFuncDecls)
_cg->throwSyntaxError(expr->functionToken, QStringLiteral("conditional function or closure declaration"));
- enterFunction(expr, /*enterName*/ true);
+ if (!enterFunction(expr, /*enterName*/ true))
+ return false;
Node::accept(expr->formals, this);
Node::accept(expr->body, this);
leaveEnvironment();
@@ -253,15 +242,25 @@ bool ScanFunctions::visit(ExpressionStatement *ast)
bool ScanFunctions::visit(FunctionExpression *ast)
{
- enterFunction(ast, /*enterName*/ false);
+ return enterFunction(ast, /*enterName*/ false);
+}
+
+bool ScanFunctions::visit(TemplateLiteral *ast)
+{
+ while (ast) {
+ if (ast->expression)
+ Node::accept(ast->expression, this);
+ ast = ast->next;
+ }
return true;
+
}
-void ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
+bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
{
if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Function name may not be eval or arguments in strict mode"));
- enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr);
+ return enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : nullptr);
}
void ScanFunctions::endVisit(FunctionExpression *)
@@ -272,7 +271,7 @@ void ScanFunctions::endVisit(FunctionExpression *)
bool ScanFunctions::visit(ObjectLiteral *ast)
{
int argc = 0;
- for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
+ for (PropertyDefinitionList *it = ast->properties; it; it = it->next) {
QString key = it->assignment->name->asString();
if (QV4::String::toArrayIndex(key) != UINT_MAX)
++argc;
@@ -290,8 +289,7 @@ bool ScanFunctions::visit(ObjectLiteral *ast)
bool ScanFunctions::visit(PropertyGetterSetter *ast)
{
TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
- enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr);
- return true;
+ return enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/nullptr);
}
void ScanFunctions::endVisit(PropertyGetterSetter *)
@@ -301,8 +299,7 @@ void ScanFunctions::endVisit(PropertyGetterSetter *)
bool ScanFunctions::visit(FunctionDeclaration *ast)
{
- enterFunction(ast, /*enterName*/ true);
- return true;
+ return enterFunction(ast, /*enterName*/ true);
}
void ScanFunctions::endVisit(FunctionDeclaration *)
@@ -391,7 +388,7 @@ bool ScanFunctions::visit(Block *ast) {
return false;
}
-void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr)
+bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, StatementList *body, FunctionExpression *expr)
{
Context *outerContext = _context;
enterEnvironment(ast, FunctionCode);
@@ -402,47 +399,48 @@ void ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete
if (expr) {
if (!outerContext->addLocalVar(name, Context::FunctionDefinition, AST::VariableDeclaration::FunctionScope, expr)) {
_cg->throwSyntaxError(ast->firstSourceLocation(), QStringLiteral("Identifier %1 has already been declared").arg(name));
- return;
+ return false;
}
}
if (name == QLatin1String("arguments"))
outerContext->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
- if (formalsContainName(formals, QStringLiteral("arguments")))
+ if (formals->containsName(QStringLiteral("arguments")))
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
- if (!name.isEmpty() && !formalsContainName(formals, name))
+ if (!name.isEmpty() && !formals->containsName(name))
_context->addLocalVar(name, Context::ThisFunctionName, QQmlJS::AST::VariableDeclaration::FunctionScope);
_context->formals = formals;
if (body && !_context->isStrict)
- checkDirectivePrologue(body->elements);
-
- 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));
- return;
- } else {
- // change the name of the earlier argument to enforce the specified lookup semantics
- QString modified = arg;
- while (_context->arguments.contains(modified))
- modified += QString(0xfffe);
- _context->arguments[duplicateIndex] = modified;
+ checkDirectivePrologue(body);
+
+ bool isSimpleParameterList = formals->isSimpleParameterList();
+
+ _context->arguments = formals->formals();
+
+ const QStringList boundNames = formals->boundNames();
+ for (int i = 0; i < boundNames.size(); ++i) {
+ const QString &arg = boundNames.at(i);
+ if (_context->isStrict || !isSimpleParameterList) {
+ bool duplicate = (boundNames.indexOf(arg, i + 1) != -1);
+ if (duplicate) {
+ _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("Duplicate parameter name '%1' is not allowed.").arg(arg));
+ return false;
}
}
if (_context->isStrict) {
if (arg == QLatin1String("eval") || arg == QLatin1String("arguments")) {
- _cg->throwSyntaxError(it->identifierToken, QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg));
- return;
+ _cg->throwSyntaxError(formals->firstSourceLocation(), QStringLiteral("'%1' cannot be used as parameter name in strict mode").arg(arg));
+ return false;
}
}
- _context->arguments += arg;
+ if (!_context->arguments.contains(arg))
+ _context->addLocalVar(arg, Context::VariableDefinition, QQmlJS::AST::VariableDeclaration::FunctionScope);
}
+ return true;
}
void ScanFunctions::calcEscapingVariables()