Check for strict mode, and store it.
authorErik Verbruggen <erik.verbruggen@digia.com>
Tue, 27 Nov 2012 15:46:04 +0000 (16:46 +0100)
committerLars Knoll <lars.knoll@digia.com>
Tue, 27 Nov 2012 15:50:36 +0000 (16:50 +0100)
Change-Id: I88e48a982eb6d4041aed085de0420d98cf96d406
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
qv4codegen.cpp
qv4codegen_p.h
qv4ir_p.h

index e605e24..0f3cedb 100644 (file)
@@ -215,9 +215,48 @@ protected:
         _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)) {
+                        if (strLit->value == QLatin1String("use strict")) {
+                            _env->isStrict = true;
+                        } else {
+                            // TODO: give a warning.
+                        }
+                        continue;
+                    }
+                }
+            }
+
+            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")) {
+                // TODO: error!
+                qDebug("TODO: give a proper error message @%u:%u", loc.startLine, loc.startColumn);
+            }
+        }
+    }
+
     virtual bool visit(Program *ast)
     {
         enterEnvironment(ast);
+        checkDirectivePrologue(ast->elements);
         return true;
     }
 
@@ -253,10 +292,17 @@ protected:
 
     virtual bool visit(VariableDeclaration *ast)
     {
+        checkName(ast->name, ast->identifierToken);
         _env->enter(ast->name.toString());
         return true;
     }
 
+    virtual bool visit(IdentifierExpression *ast)
+    {
+        checkName(ast->name, ast->identifierToken);
+        return true;
+    }
+
     virtual bool visit(FunctionExpression *ast)
     {
         if (_env) {
@@ -264,6 +310,8 @@ protected:
             _env->enter(ast->name.toString());
         }
         enterEnvironment(ast);
+        if (ast->body)
+            checkDirectivePrologue(ast->body->elements);
         return true;
     }
 
@@ -278,6 +326,8 @@ protected:
         _env->hasNestedFunctions = true;
         _env->enter(ast->name.toString());
         enterEnvironment(ast);
+        if (ast->body)
+            checkDirectivePrologue(ast->body->elements);
         return true;
     }
 
@@ -286,6 +336,17 @@ protected:
         leaveEnvironment();
     }
 
+    virtual bool visit(WithStatement *ast)
+    {
+        if (_env->isStrict) {
+            // TODO: give a proper error message
+            qDebug("TODO: give proper error message @%u:%u", ast->withToken.startLine, ast->withToken.startColumn);
+            return false;
+        }
+
+        return true;
+    }
+
     Codegen *_cg;
     Environment *_env;
     QStack<Environment *> _envStack;
@@ -1515,6 +1576,7 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
     function->hasDirectEval = _env->hasDirectEval;
     function->hasNestedFunctions = _env->hasNestedFunctions;
     function->maxNumberOfArguments = _env->maxNumberOfArguments;
+    function->isStrict = _env->isStrict;
 
     // variables in global code are properties of the global context object, not locals as with other functions.
     if (_mode == FunctionCode) {
index c830345..4622d25 100644 (file)
@@ -108,12 +108,15 @@ protected:
         int maxNumberOfArguments;
         bool hasDirectEval;
         bool hasNestedFunctions;
+        bool isStrict;
 
         Environment(Environment *parent)
             : parent(parent)
             , maxNumberOfArguments(0)
             , hasDirectEval(false)
-            , hasNestedFunctions(false) {}
+            , hasNestedFunctions(false)
+            , isStrict(false)
+        {}
 
         int findMember(const QString &name) const
         {
index 740ca9b..ee91807 100644 (file)
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -602,9 +602,11 @@ struct Function {
     const uchar *codeData;
     JSC::MacroAssemblerCodeRef codeRef;
 
+    int insideWith;
+
     bool hasDirectEval: 1;
     bool hasNestedFunctions: 1;
-    int insideWith;
+    bool isStrict: 1;
 
     template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
 
@@ -615,9 +617,10 @@ struct Function {
         , maxNumberOfArguments(0)
         , code(0)
         , codeData(0)
+        , insideWith(0)
         , hasDirectEval(false)
         , hasNestedFunctions(false)
-        , insideWith(0)
+        , isStrict(false)
     { this->name = newString(name); }
 
     ~Function();