Cleanup: Separate JS environment scanner class declaration from definition
authorSimon Hausmann <simon.hausmann@digia.com>
Tue, 6 Aug 2013 11:59:47 +0000 (13:59 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 22 Aug 2013 02:24:10 +0000 (04:24 +0200)
This will allow the use of it from outside.

Change-Id: Ia05a17b4b4f3e772554979e215a6252a75a63273
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/compiler/qv4codegen.cpp
src/qml/compiler/qv4codegen_p.h

index 6c913a6..e97be71 100644 (file)
 using namespace QQmlJS;
 using namespace AST;
 
-class Codegen::ScanFunctions: Visitor
-{
-    typedef QV4::TemporaryAssignment<bool> TemporaryBoolAssignment;
-public:
-    ScanFunctions(Codegen *cg, const QString &sourceCode)
-        : _cg(cg)
-        , _sourceCode(sourceCode)
-        , _env(0)
-        , _inFuncBody(false)
-        , _allowFuncDecls(true)
-    {
-    }
-
-    void operator()(Node *node)
-    {
-        if (node)
-            node->accept(this);
-    }
+Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode)
+    : _cg(cg)
+    , _sourceCode(sourceCode)
+    , _env(0)
+    , _inFuncBody(false)
+    , _allowFuncDecls(true)
+{
+}
 
-    inline void enterEnvironment(Node *node)
-    {
-        Environment *e = _cg->newEnvironment(node, _env);
-        if (!e->isStrict)
-            e->isStrict = _cg->_strictMode;
-        _envStack.append(e);
-        _env = e;
-    }
+void Codegen::ScanFunctions::operator()(Node *node)
+{
+    if (node)
+        node->accept(this);
+}
 
-    inline void leaveEnvironment()
-    {
-        _envStack.pop();
-        _env = _envStack.isEmpty() ? 0 : _envStack.top();
-    }
+void Codegen::ScanFunctions::enterEnvironment(Node *node)
+{
+    Environment *e = _cg->newEnvironment(node, _env);
+    if (!e->isStrict)
+        e->isStrict = _cg->_strictMode;
+    _envStack.append(e);
+    _env = e;
+}
 
-protected:
-    using Visitor::visit;
-    using Visitor::endVisit;
+void Codegen::ScanFunctions::leaveEnvironment()
+{
+    _envStack.pop();
+    _env = _envStack.isEmpty() ? 0 : _envStack.top();
+}
 
-    void checkDirectivePrologue(SourceElements *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 == QStringLiteral("use strict")) {
-                            _env->isStrict = true;
-                        } else {
-                            // TODO: give a warning.
-                        }
+void Codegen::ScanFunctions::checkDirectivePrologue(SourceElements *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 == QStringLiteral("use strict")) {
+                        _env->isStrict = true;
+                    } else {
+                        // TODO: give a warning.
                     }
+                    continue;
                 }
             }
-
-            break;
         }
+
+        break;
     }
+}
 
-    void checkName(const QStringRef &name, const SourceLocation &loc)
-    {
-        if (_env->isStrict) {
-            if (name == QLatin1String("implements")
-                    || name == QLatin1String("interface")
-                    || name == QLatin1String("let")
-                    || name == QLatin1String("package")
-                    || name == QLatin1String("private")
-                    || name == QLatin1String("protected")
-                    || name == QLatin1String("public")
-                    || name == QLatin1String("static")
-                    || name == QLatin1String("yield")) {
-                _cg->throwSyntaxError(loc, QCoreApplication::translate("qv4codegen", "Unexpected strict mode reserved word"));
-            }
+void Codegen::ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc)
+{
+    if (_env->isStrict) {
+        if (name == QLatin1String("implements")
+                || name == QLatin1String("interface")
+                || name == QLatin1String("let")
+                || name == QLatin1String("package")
+                || name == QLatin1String("private")
+                || name == QLatin1String("protected")
+                || name == QLatin1String("public")
+                || name == QLatin1String("static")
+                || name == QLatin1String("yield")) {
+            _cg->throwSyntaxError(loc, QCoreApplication::translate("qv4codegen", "Unexpected strict mode reserved word"));
         }
     }
-    void checkForArguments(AST::FormalParameterList *parameters)
-    {
-        while (parameters) {
-            if (parameters->name == QStringLiteral("arguments"))
-                _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
-            parameters = parameters->next;
-        }
+}
+void Codegen::ScanFunctions::checkForArguments(AST::FormalParameterList *parameters)
+{
+    while (parameters) {
+        if (parameters->name == QStringLiteral("arguments"))
+            _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+        parameters = parameters->next;
     }
+}
 
-    virtual bool visit(Program *ast)
-    {
-        enterEnvironment(ast);
-        checkDirectivePrologue(ast->elements);
-        return true;
-    }
+bool Codegen::ScanFunctions::visit(Program *ast)
+{
+    enterEnvironment(ast);
+    checkDirectivePrologue(ast->elements);
+    return true;
+}
 
-    virtual void endVisit(Program *)
-    {
-        leaveEnvironment();
-    }
+void Codegen::ScanFunctions::endVisit(Program *)
+{
+    leaveEnvironment();
+}
 
-    virtual bool visit(CallExpression *ast)
-    {
-        if (! _env->hasDirectEval) {
-            if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
-                if (id->name == QStringLiteral("eval")) {
-                    if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown)
-                        _env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
-                    _env->hasDirectEval = true;
-                }
+bool Codegen::ScanFunctions::visit(CallExpression *ast)
+{
+    if (! _env->hasDirectEval) {
+        if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
+            if (id->name == QStringLiteral("eval")) {
+                if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown)
+                    _env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
+                _env->hasDirectEval = true;
             }
         }
-        int argc = 0;
-        for (ArgumentList *it = ast->arguments; it; it = it->next)
-            ++argc;
-        _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
-        return true;
     }
+    int argc = 0;
+    for (ArgumentList *it = ast->arguments; it; it = it->next)
+        ++argc;
+    _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
+    return true;
+}
 
-    virtual bool visit(NewMemberExpression *ast)
-    {
-        int argc = 0;
-        for (ArgumentList *it = ast->arguments; it; it = it->next)
-            ++argc;
-        _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
-        return true;
-    }
+bool Codegen::ScanFunctions::visit(NewMemberExpression *ast)
+{
+    int argc = 0;
+    for (ArgumentList *it = ast->arguments; it; it = it->next)
+        ++argc;
+    _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
+    return true;
+}
 
-    virtual bool visit(ArrayLiteral *ast)
-    {
-        int index = 0;
-        for (ElementList *it = ast->elements; it; it = it->next) {
-            for (Elision *elision = it->elision; elision; elision = elision->next)
-                ++index;
+bool Codegen::ScanFunctions::visit(ArrayLiteral *ast)
+{
+    int index = 0;
+    for (ElementList *it = ast->elements; it; it = it->next) {
+        for (Elision *elision = it->elision; elision; elision = elision->next)
             ++index;
-        }
-        if (ast->elision) {
-            for (Elision *elision = ast->elision->next; elision; elision = elision->next)
-                ++index;
-        }
-        _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, index);
-        return true;
-    }
-
-    virtual bool visit(VariableDeclaration *ast)
-    {
-        if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
-            _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Variable name may not be eval or arguments in strict mode"));
-        checkName(ast->name, ast->identifierToken);
-        if (ast->name == QLatin1String("arguments"))
-            _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
-        _env->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration);
-        return true;
+        ++index;
     }
-
-    virtual bool visit(IdentifierExpression *ast)
-    {
-        checkName(ast->name, ast->identifierToken);
-        if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments"))
-            _env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
-        return true;
+    if (ast->elision) {
+        for (Elision *elision = ast->elision->next; elision; elision = elision->next)
+            ++index;
     }
+    _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, index);
+    return true;
+}
 
-    virtual bool visit(ExpressionStatement *ast)
-    {
-        if (FunctionExpression* expr = AST::cast<AST::FunctionExpression*>(ast->expression)) {
-            if (!_allowFuncDecls)
-                _cg->throwSyntaxError(expr->functionToken, QCoreApplication::translate("qv4codegen", "conditional function or closure declaration"));
-
-            enterFunction(expr, /*enterName*/ true);
-            Node::accept(expr->formals, this);
-            Node::accept(expr->body, this);
-            leaveEnvironment();
-            return false;
-        } else {
-            SourceLocation firstToken = ast->firstSourceLocation();
-            if (_sourceCode.midRef(firstToken.offset, firstToken.length) == QStringLiteral("function")) {
-                _cg->throwSyntaxError(firstToken, QCoreApplication::translate("qv4codegen", "unexpected token"));
-            }
-        }
-        return true;
-    }
+bool Codegen::ScanFunctions::visit(VariableDeclaration *ast)
+{
+    if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
+        _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Variable name may not be eval or arguments in strict mode"));
+    checkName(ast->name, ast->identifierToken);
+    if (ast->name == QLatin1String("arguments"))
+        _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+    _env->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration);
+    return true;
+}
 
-    virtual bool visit(FunctionExpression *ast)
-    {
-        enterFunction(ast, /*enterName*/ false);
-        return true;
-    }
+bool Codegen::ScanFunctions::visit(IdentifierExpression *ast)
+{
+    checkName(ast->name, ast->identifierToken);
+    if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments"))
+        _env->usesArgumentsObject = Environment::ArgumentsObjectUsed;
+    return true;
+}
 
-    void enterFunction(FunctionExpression *ast, bool enterName, bool isExpression = true)
-    {
-        if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
-            _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Function name may not be eval or arguments in strict mode"));
-        enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0, isExpression);
-    }
+bool Codegen::ScanFunctions::visit(ExpressionStatement *ast)
+{
+    if (FunctionExpression* expr = AST::cast<AST::FunctionExpression*>(ast->expression)) {
+        if (!_allowFuncDecls)
+            _cg->throwSyntaxError(expr->functionToken, QCoreApplication::translate("qv4codegen", "conditional function or closure declaration"));
 
-    virtual void endVisit(FunctionExpression *)
-    {
+        enterFunction(expr, /*enterName*/ true);
+        Node::accept(expr->formals, this);
+        Node::accept(expr->body, this);
         leaveEnvironment();
-    }
-
-    virtual bool visit(ObjectLiteral *ast)
-    {
-        int argc = 0;
-        for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
-            ++argc;
-            if (AST::cast<AST::PropertyGetterSetter *>(it->assignment))
-                ++argc;
-        }
-        _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
-
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
-        Node::accept(ast->properties, this);
         return false;
+    } else {
+        SourceLocation firstToken = ast->firstSourceLocation();
+        if (_sourceCode.midRef(firstToken.offset, firstToken.length) == QStringLiteral("function")) {
+            _cg->throwSyntaxError(firstToken, QCoreApplication::translate("qv4codegen", "unexpected token"));
+        }
     }
+    return true;
+}
 
-    virtual bool visit(PropertyGetterSetter *ast)
-    {
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
-        enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/0, /*isExpression*/false);
-        return true;
-    }
+bool Codegen::ScanFunctions::visit(FunctionExpression *ast)
+{
+    enterFunction(ast, /*enterName*/ false);
+    return true;
+}
 
-    virtual void endVisit(PropertyGetterSetter *)
-    {
-        leaveEnvironment();
-    }
+void Codegen::ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName, bool isExpression)
+{
+    if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
+        _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Function name may not be eval or arguments in strict mode"));
+    enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0, isExpression);
+}
 
-    virtual bool visit(FunctionDeclaration *ast)
-    {
-        enterFunction(ast, /*enterName*/ true, /*isExpression */false);
-        return true;
-    }
+void Codegen::ScanFunctions::endVisit(FunctionExpression *)
+{
+    leaveEnvironment();
+}
 
-    virtual void endVisit(FunctionDeclaration *)
-    {
-        leaveEnvironment();
+bool Codegen::ScanFunctions::visit(ObjectLiteral *ast)
+{
+    int argc = 0;
+    for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
+        ++argc;
+        if (AST::cast<AST::PropertyGetterSetter *>(it->assignment))
+            ++argc;
     }
+    _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
 
-    virtual bool visit(FunctionBody *ast)
-    {
-        TemporaryBoolAssignment inFuncBody(_inFuncBody, true);
-        Node::accept(ast->elements, this);
-        return false;
-    }
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
+    Node::accept(ast->properties, this);
+    return false;
+}
 
-    virtual bool visit(WithStatement *ast)
-    {
-        if (_env->isStrict) {
-            _cg->throwSyntaxError(ast->withToken, QCoreApplication::translate("qv4codegen", "'with' statement is not allowed in strict mode"));
-            return false;
-        }
+bool Codegen::ScanFunctions::visit(PropertyGetterSetter *ast)
+{
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true);
+    enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/0, /*isExpression*/false);
+    return true;
+}
 
-        return true;
-    }
+void Codegen::ScanFunctions::endVisit(PropertyGetterSetter *)
+{
+    leaveEnvironment();
+}
+
+bool Codegen::ScanFunctions::visit(FunctionDeclaration *ast)
+{
+    enterFunction(ast, /*enterName*/ true, /*isExpression */false);
+    return true;
+}
 
-    virtual bool visit(IfStatement *ast) {
-        Node::accept(ast->expression, this);
+void Codegen::ScanFunctions::endVisit(FunctionDeclaration *)
+{
+    leaveEnvironment();
+}
 
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody);
-        Node::accept(ast->ok, this);
-        Node::accept(ast->ko, this);
+bool Codegen::ScanFunctions::visit(FunctionBody *ast)
+{
+    TemporaryBoolAssignment inFuncBody(_inFuncBody, true);
+    Node::accept(ast->elements, this);
+    return false;
+}
 
+bool Codegen::ScanFunctions::visit(WithStatement *ast)
+{
+    if (_env->isStrict) {
+        _cg->throwSyntaxError(ast->withToken, QCoreApplication::translate("qv4codegen", "'with' statement is not allowed in strict mode"));
         return false;
     }
 
-    virtual bool visit(WhileStatement *ast) {
-        Node::accept(ast->expression, this);
+    return true;
+}
 
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody);
-        Node::accept(ast->statement, this);
+bool Codegen::ScanFunctions::visit(IfStatement *ast) {
+    Node::accept(ast->expression, this);
 
-        return false;
-    }
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody);
+    Node::accept(ast->ok, this);
+    Node::accept(ast->ko, this);
 
-    virtual bool visit(DoWhileStatement *ast) {
-        {
-            TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
-            Node::accept(ast->statement, this);
-        }
-        Node::accept(ast->expression, this);
-        return false;
-    }
+    return false;
+}
+
+bool Codegen::ScanFunctions::visit(WhileStatement *ast) {
+    Node::accept(ast->expression, this);
+
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody);
+    Node::accept(ast->statement, this);
 
-    virtual bool visit(ForStatement *ast) {
-        Node::accept(ast->initialiser, this);
-        Node::accept(ast->condition, this);
-        Node::accept(ast->expression, this);
+    return false;
+}
 
+bool Codegen::ScanFunctions::visit(DoWhileStatement *ast) {
+    {
         TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
         Node::accept(ast->statement, this);
-
-        return false;
     }
+    Node::accept(ast->expression, this);
+    return false;
+}
 
-    virtual bool visit(LocalForStatement *ast) {
-        Node::accept(ast->declarations, this);
-        Node::accept(ast->condition, this);
-        Node::accept(ast->expression, this);
+bool Codegen::ScanFunctions::visit(ForStatement *ast) {
+    Node::accept(ast->initialiser, this);
+    Node::accept(ast->condition, this);
+    Node::accept(ast->expression, this);
 
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
-        Node::accept(ast->statement, this);
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+    Node::accept(ast->statement, this);
 
-        return false;
-    }
+    return false;
+}
 
-    virtual bool visit(ForEachStatement *ast) {
-        Node::accept(ast->initialiser, this);
-        Node::accept(ast->expression, this);
+bool Codegen::ScanFunctions::visit(LocalForStatement *ast) {
+    Node::accept(ast->declarations, this);
+    Node::accept(ast->condition, this);
+    Node::accept(ast->expression, this);
 
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
-        Node::accept(ast->statement, this);
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+    Node::accept(ast->statement, this);
 
-        return false;
-    }
+    return false;
+}
 
-    virtual bool visit(LocalForEachStatement *ast) {
-        Node::accept(ast->declaration, this);
-        Node::accept(ast->expression, this);
+bool Codegen::ScanFunctions::visit(ForEachStatement *ast) {
+    Node::accept(ast->initialiser, this);
+    Node::accept(ast->expression, this);
 
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
-        Node::accept(ast->statement, this);
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+    Node::accept(ast->statement, this);
 
-        return false;
-    }
+    return false;
+}
 
-    virtual bool visit(Block *ast) {
-        TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _env->isStrict ? false : _allowFuncDecls);
-        Node::accept(ast->statements, this);
-        return false;
-    }
+bool Codegen::ScanFunctions::visit(LocalForEachStatement *ast) {
+    Node::accept(ast->declaration, this);
+    Node::accept(ast->expression, this);
 
-private:
-    void enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr, bool isExpression)
-    {
-        bool wasStrict = false;
-        if (_env) {
-            _env->hasNestedFunctions = true;
-            // The identifier of a function expression cannot be referenced from the enclosing environment.
-            if (expr)
-                _env->enter(name, Environment::FunctionDefinition, expr);
-            if (name == QLatin1String("arguments"))
-                _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
-            wasStrict = _env->isStrict;
-        }
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict);
+    Node::accept(ast->statement, this);
 
-        enterEnvironment(ast);
-        checkForArguments(formals);
+    return false;
+}
 
-        _env->isNamedFunctionExpression = isExpression && !name.isEmpty();
-        _env->formals = formals;
+bool Codegen::ScanFunctions::visit(Block *ast) {
+    TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _env->isStrict ? false : _allowFuncDecls);
+    Node::accept(ast->statements, this);
+    return false;
+}
 
-        if (body)
-            checkDirectivePrologue(body->elements);
+void Codegen::ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr, bool isExpression)
+{
+    bool wasStrict = false;
+    if (_env) {
+        _env->hasNestedFunctions = true;
+        // The identifier of a function expression cannot be referenced from the enclosing environment.
+        if (expr)
+            _env->enter(name, Environment::FunctionDefinition, expr);
+        if (name == QLatin1String("arguments"))
+            _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed;
+        wasStrict = _env->isStrict;
+    }
 
-        if (wasStrict || _env->isStrict) {
-            QStringList args;
-            for (FormalParameterList *it = formals; it; it = it->next) {
-                QString arg = it->name.toString();
-                if (args.contains(arg))
-                    _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "Duplicate parameter name '%1' is not allowed in strict mode").arg(arg));
-                if (arg == QLatin1String("eval") || arg == QLatin1String("arguments"))
-                    _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "'%1' cannot be used as parameter name in strict mode").arg(arg));
-                args += arg;
-            }
+    enterEnvironment(ast);
+    checkForArguments(formals);
+
+    _env->isNamedFunctionExpression = isExpression && !name.isEmpty();
+    _env->formals = formals;
+
+    if (body)
+        checkDirectivePrologue(body->elements);
+
+    if (wasStrict || _env->isStrict) {
+        QStringList args;
+        for (FormalParameterList *it = formals; it; it = it->next) {
+            QString arg = it->name.toString();
+            if (args.contains(arg))
+                _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "Duplicate parameter name '%1' is not allowed in strict mode").arg(arg));
+            if (arg == QLatin1String("eval") || arg == QLatin1String("arguments"))
+                _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "'%1' cannot be used as parameter name in strict mode").arg(arg));
+            args += arg;
         }
     }
+}
 
-private: // fields:
-    Codegen *_cg;
-    const QString _sourceCode;
-    Environment *_env;
-    QStack<Environment *> _envStack;
-
-    bool _inFuncBody;
-    bool _allowFuncDecls;
-};
 
 Codegen::Codegen(bool strict)
     : _module(0)
index 85c38d8..2aa4b42 100644 (file)
 #include <private/qqmljsastvisitor_p.h>
 #include <private/qqmljsast_p.h>
 #include <QtCore/QStringList>
+#include <QStack>
 #include <qqmlerror.h>
 #include <assert.h>
+#include <private/qv4util_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -433,7 +435,75 @@ protected:
 
     QList<QQmlError> _errors;
 
-    class ScanFunctions;
+    class ScanFunctions: Visitor
+    {
+        typedef QV4::TemporaryAssignment<bool> TemporaryBoolAssignment;
+    public:
+        ScanFunctions(Codegen *cg, const QString &sourceCode);
+        void operator()(AST::Node *node);
+
+        void enterEnvironment(AST::Node *node);
+        void leaveEnvironment();
+
+    protected:
+        using Visitor::visit;
+        using Visitor::endVisit;
+
+        void checkDirectivePrologue(AST::SourceElements *ast);
+
+        void checkName(const QStringRef &name, const AST::SourceLocation &loc);
+        void checkForArguments(AST::FormalParameterList *parameters);
+
+        virtual bool visit(AST::Program *ast);
+        virtual void endVisit(AST::Program *);
+
+        virtual bool visit(AST::CallExpression *ast);
+        virtual bool visit(AST::NewMemberExpression *ast);
+        virtual bool visit(AST::ArrayLiteral *ast);
+        virtual bool visit(AST::VariableDeclaration *ast);
+        virtual bool visit(AST::IdentifierExpression *ast);
+        virtual bool visit(AST::ExpressionStatement *ast);
+        virtual bool visit(AST::FunctionExpression *ast);
+
+        void enterFunction(AST::FunctionExpression *ast, bool enterName, bool isExpression = true);
+
+        virtual void endVisit(AST::FunctionExpression *);
+
+        virtual bool visit(AST::ObjectLiteral *ast);
+
+        virtual bool visit(AST::PropertyGetterSetter *ast);
+        virtual void endVisit(AST::PropertyGetterSetter *);
+
+        virtual bool visit(AST::FunctionDeclaration *ast);
+        virtual void endVisit(AST::FunctionDeclaration *);
+
+        virtual bool visit(AST::FunctionBody *ast);
+
+        virtual bool visit(AST::WithStatement *ast);
+
+        virtual bool visit(AST::IfStatement *ast);
+        virtual bool visit(AST::WhileStatement *ast);
+        virtual bool visit(AST::DoWhileStatement *ast);
+        virtual bool visit(AST::ForStatement *ast);
+        virtual bool visit(AST::LocalForStatement *ast);
+        virtual bool visit(AST::ForEachStatement *ast);
+        virtual bool visit(AST::LocalForEachStatement *ast);
+
+        virtual bool visit(AST::Block *ast);
+
+    protected:
+        void enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::FunctionBody *body, AST::FunctionExpression *expr, bool isExpression);
+
+    // fields:
+        Codegen *_cg;
+        const QString _sourceCode;
+        Environment *_env;
+        QStack<Environment *> _envStack;
+
+        bool _inFuncBody;
+        bool _allowFuncDecls;
+    };
+
 };
 
 class RuntimeCodegen : public Codegen