From 1f2dc8856e04047648163445871b891fa898a3c1 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 27 Nov 2012 16:46:04 +0100 Subject: [PATCH] Check for strict mode, and store it. Change-Id: I88e48a982eb6d4041aed085de0420d98cf96d406 Reviewed-by: Lars Knoll --- qv4codegen.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qv4codegen_p.h | 5 ++++- qv4ir_p.h | 7 +++++-- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/qv4codegen.cpp b/qv4codegen.cpp index e605e24..0f3cedb 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -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(it->element)) { + if (ExpressionStatement *expr = cast(stmt->statement)) { + if (StringLiteral *strLit = cast(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 _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) { diff --git a/qv4codegen_p.h b/qv4codegen_p.h index c830345..4622d25 100644 --- a/qv4codegen_p.h +++ b/qv4codegen_p.h @@ -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 { diff --git a/qv4ir_p.h b/qv4ir_p.h index 740ca9b..ee91807 100644 --- 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 _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(); -- 2.7.4