Allow return statement when parsing bindings
authorLars Knoll <lars.knoll@digia.com>
Sun, 2 Jun 2013 14:58:01 +0000 (16:58 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Sun, 2 Jun 2013 16:27:46 +0000 (18:27 +0200)
An explicit return statement was allowed in bindings with v8 (as
they were rewritten as function closures. There's no reason to forbid them
now.

Fixes two tests in qqmlecmascript.

Change-Id: I27a6f88d17d8c35b37735ad321b7607f09b1e67c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/v4/qv4codegen.cpp
src/qml/qml/v4/qv4codegen_p.h
src/qml/qml/v4/qv4script.cpp
src/qml/qml/v4/qv4script_p.h

index 1b8473d..fcbca56 100644 (file)
@@ -2007,7 +2007,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
         f = f->outer;
     }
 
-    if (!e->parent && (!f || !f->insideWithOrCatch) && _mode != EvalCode && (!f || f->name != name))
+    if (!e->parent && (!f || !f->insideWithOrCatch) && _mode != EvalCode && _mode != QmlBinding && (!f || f->name != name))
         return _block->GLOBALNAME(name, line, col);
 
     // global context or with. Lookup by name
@@ -2631,7 +2631,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
         }
         if (args) {
             V4IR::ExprList *next = function->New<V4IR::ExprList>();
-            next->expr = entryBlock->CONST(V4IR::BoolType, mode == EvalCode);
+            next->expr = entryBlock->CONST(V4IR::BoolType, (mode == EvalCode || mode == QmlBinding));
             next->next = args;
             args = next;
 
@@ -2819,7 +2819,7 @@ bool Codegen::visit(EmptyStatement *)
 
 bool Codegen::visit(ExpressionStatement *ast)
 {
-    if (_mode == EvalCode) {
+    if (_mode == EvalCode || _mode == QmlBinding) {
         Result e = expression(ast->expression);
         if (*e)
             move(_block->TEMP(_returnAddress), *e);
@@ -3017,7 +3017,7 @@ bool Codegen::visit(LocalForStatement *ast)
 
 bool Codegen::visit(ReturnStatement *ast)
 {
-    if (_mode != FunctionCode)
+    if (_mode != FunctionCode && _mode != QmlBinding)
         throwSyntaxError(ast->returnToken, QCoreApplication::translate("qv4codegen", "Return statement outside of function"));
     if (ast->expression) {
         Result expr = expression(ast->expression);
index 9e95d89..a4d20e3 100644 (file)
@@ -78,7 +78,8 @@ public:
     enum Mode {
         GlobalCode,
         EvalCode,
-        FunctionCode
+        FunctionCode,
+        QmlBinding
     };
 
     V4IR::Function *operator()(const QString &fileName,
index c0e2495..0e11831 100644 (file)
@@ -159,7 +159,8 @@ void Script::parse()
                 inheritedLocals.append(*i ? (*i)->toQString() : QString());
 
         Codegen cg(scope, strictMode);
-        V4IR::Function *globalIRCode = cg(sourceFile, sourceCode, program, &module, QQmlJS::Codegen::EvalCode, inheritedLocals);
+        V4IR::Function *globalIRCode = cg(sourceFile, sourceCode, program, &module,
+                                          parseAsBinding ? QQmlJS::Codegen::QmlBinding : QQmlJS::Codegen::EvalCode, inheritedLocals);
         QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(v4, &module));
         if (inheritContext)
             isel->setUseFastLookups(false);
index 388d0fa..f46d300 100644 (file)
@@ -54,11 +54,11 @@ struct Q_QML_EXPORT Script {
     Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
         : sourceFile(source), line(line), column(column), sourceCode(sourceCode)
         , scope(scope), strictMode(false), inheritContext(false), parsed(false)
-        , vmFunction(0) {}
+        , vmFunction(0), parseAsBinding(false) {}
     Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
         : sourceFile(source), line(line), column(column), sourceCode(sourceCode)
         , scope(engine->rootContext), strictMode(true), inheritContext(true), parsed(false)
-        , qml(Value::fromObject(qml)), vmFunction(0) {}
+        , qml(Value::fromObject(qml)), vmFunction(0), parseAsBinding(true) {}
     QString sourceFile;
     int line;
     int column;
@@ -69,6 +69,7 @@ struct Q_QML_EXPORT Script {
     bool parsed;
     QV4::PersistentValue qml;
     Function *vmFunction;
+    bool parseAsBinding;
 
     void parse();
     Value run();