Fix direct vs indirect calls to eval (15.1.2.11)
authorLars Knoll <lars.knoll@digia.com>
Wed, 23 Jan 2013 09:07:18 +0000 (10:07 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Wed, 23 Jan 2013 09:36:42 +0000 (10:36 +0100)
Change-Id: I6f5dc4a1cc538f255c614838821dd2b379ba2832
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qmljs_engine.cpp
qmljs_engine.h
qmljs_runtime.cpp
qv4globalobject.cpp
qv4globalobject.h
tests/TestExpectations

index c2fe43c..2008dbd 100644 (file)
@@ -108,6 +108,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     id_value = identifier(QStringLiteral("value"));
     id_get = identifier(QStringLiteral("get"));
     id_set = identifier(QStringLiteral("set"));
+    id_eval = identifier(QStringLiteral("eval"));
 
     objectPrototype = new (memoryManager) ObjectPrototype();
     stringPrototype = new (memoryManager) StringPrototype(rootContext);
@@ -218,7 +219,8 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     glo->defineReadonlyProperty(this, QStringLiteral("NaN"), Value::fromDouble(nan("")));
     glo->defineReadonlyProperty(this, QStringLiteral("Infinity"), Value::fromDouble(INFINITY));
 
-    glo->defineDefaultProperty(rootContext, QStringLiteral("eval"), Value::fromObject(new (memoryManager) EvalFunction(rootContext)));
+    evalFunction = new (memoryManager) EvalFunction(rootContext);
+    glo->defineDefaultProperty(rootContext, QStringLiteral("eval"), Value::fromObject(evalFunction));
 
     glo->defineDefaultProperty(rootContext, QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
     glo->defineDefaultProperty(rootContext, QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
index afc0b3b..2b8b8b5 100644 (file)
@@ -90,6 +90,7 @@ struct ReferenceErrorPrototype;
 struct SyntaxErrorPrototype;
 struct TypeErrorPrototype;
 struct URIErrorPrototype;
+struct EvalFunction;
 
 class RegExp;
 
@@ -137,6 +138,8 @@ struct ExecutionEngine
     TypeErrorPrototype *typeErrorPrototype;
     URIErrorPrototype *uRIErrorPrototype;
 
+    EvalFunction *evalFunction;
+
     QVector<PropertyDescriptor> argumentsAccessors;
 
     String *id_length;
@@ -152,6 +155,7 @@ struct ExecutionEngine
     String *id_value;
     String *id_get;
     String *id_set;
+    String *id_eval;
 
     struct ExceptionHandler {
         ExecutionContext *context;
index c0202d9..b6750ff 100644 (file)
@@ -44,6 +44,7 @@
 #include "qv4object.h"
 #include "qv4ir_p.h"
 #include "qv4objectproto.h"
+#include "qv4globalobject.h"
 #include "private/qlocale_tools_p.h"
 
 #include <QtCore/qmath.h>
@@ -740,6 +741,9 @@ Value __qmljs_call_activation_property(ExecutionContext *context, String *name,
 
     Value thisObject = base ? Value::fromObject(base) : Value::undefinedValue();
 
+    if (o == context->engine->evalFunction && name == context->engine->id_eval)
+        return static_cast<EvalFunction *>(o)->call(context, thisObject, args, argc, true);
+
     return o->call(context, thisObject, args, argc);
 }
 
index 059dfe7..3a6b34d 100644 (file)
@@ -307,8 +307,13 @@ static QString decode(const QString &input, const QString &reservedSet, bool *ok
 }
 
 
+EvalFunction::EvalFunction(ExecutionContext *scope)
+    : FunctionObject(scope)
+{
+    name = scope->engine->id_eval;
+}
 
-Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc)
+Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc, bool directCall)
 {
     if (argc < 1)
         return Value::undefinedValue();
@@ -316,9 +321,6 @@ Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value
     if (!args[0].isString())
         return args[0];
 
-    // ### how to determine this correctly?
-    bool directCall = true;
-
     const QString code = args[0].stringValue()->toQString();
     QQmlJS::VM::Function *f = parseSource(context, QStringLiteral("eval code"), code, QQmlJS::Codegen::EvalCode);
     if (!f)
@@ -326,16 +328,18 @@ Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value
 
     bool strict = f->isStrict || context->strictMode;
 
-    ExecutionContext k, *ctx;
+    ExecutionContext k;
+
+    ExecutionContext *ctx = context;
     if (!directCall) {
-        qDebug() << "!direct";
-        // ###
-    } else if (strict) {
+        // the context for eval should be the global scope
+        while (ctx->parent)
+            ctx = ctx->parent;
+    }
+
+    if (strict) {
         ctx = &k;
         ctx->initCallContext(context, context->thisObject, this, args, argc);
-    } else {
-        // use the surrounding context
-        ctx = context;
     }
 
     // set the correct strict mode flag on the context
@@ -352,10 +356,11 @@ Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value
     return result;
 }
 
-EvalFunction::EvalFunction(ExecutionContext *scope)
-    : FunctionObject(scope)
+
+Value EvalFunction::call(ExecutionContext *context, Value thisObject, Value *args, int argc)
 {
-    name = scope->engine->newString(QLatin1String("eval"));
+    // indirect call
+    return call(context, thisObject, args, argc, false);
 }
 
 QQmlJS::VM::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ctx,
index 3ea7b38..c335029 100644 (file)
@@ -57,6 +57,7 @@ struct EvalFunction : FunctionObject
                                              QQmlJS::Codegen::Mode mode);
 
     virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc);
+    Value call(ExecutionContext *context, Value thisObject, Value *args, int argc, bool directCall);
 };
 
 struct GlobalFunctions
index 1618263..0eb51ee 100644 (file)
@@ -8,11 +8,7 @@ S15.1.3.2_A2.5_T1
 
 
 # Tests failing that are supposed to pass.
-10.4.2-1-1 failing
 10.4.2-1-2 failing
-10.4.2-1-3 failing
-10.4.2-1-4 failing
-10.4.2-1-5 failing
 10.4.3-1-104 failing
 10.4.3-1-106 failing
 10.4.3-1-17-s failing