Properly set up the 'this' pointer
authorLars Knoll <lars.knoll@digia.com>
Mon, 10 Dec 2012 18:30:08 +0000 (19:30 +0100)
committerLars Knoll <lars.knoll@digia.com>
Mon, 10 Dec 2012 19:08:26 +0000 (20:08 +0100)
Make sure the this pointer is setup correctly for
function calls. Also make sure we set the strict mode
flag correctly in all functions.

Change-Id: Idaacc92bf6469145b7addfac2bbddea588e85c2d
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
qmljs_engine.cpp
qmljs_environment.cpp
qmljs_objects.cpp
qmljs_runtime.cpp
qv4codegen.cpp

index a694d3e..4da9564 100644 (file)
@@ -177,6 +177,7 @@ ExecutionEngine::ExecutionEngine(MemoryManager *memoryManager, EvalISelFactory *
     VM::Object *glo = newObject(/*rootContext*/);
     globalObject = Value::fromObject(glo);
     rootContext->activation = glo;
+    rootContext->thisObject = Value::fromObject(glo);
 
     glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor);
     glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor);
index 4f2f798..9f900f9 100644 (file)
@@ -210,7 +210,7 @@ void ExecutionContext::init(ExecutionEngine *eng)
 {
     engine = eng;
     parent = 0;
-    thisObject = Value::nullValue();
+    thisObject = eng->globalObject;
 
     function = 0;
     arguments = 0;
@@ -385,11 +385,18 @@ void ExecutionContext::initCallContext(ExecutionContext *parent, const Value tha
 
     engine = parent->engine;
     this->parent = parent;
-    thisObject = that;
 
     function = f;
     strictMode = f->strictMode;
 
+    thisObject = that;
+    if (!strictMode && !thisObject.isObject()) {
+        if (thisObject.isUndefined() || thisObject.isNull())
+            thisObject = engine->globalObject;
+        else
+            thisObject = thisObject.toObject(this);
+    }
+
     arguments = args;
     argumentCount = argc;
     if (function->needsActivation || argc < function->formalParameterCount){
index d74a501..6e0af63 100644 (file)
@@ -450,7 +450,7 @@ Value FunctionObject::construct(ExecutionContext *context, Value *args, int argc
 {
     ExecutionContext k;
     ExecutionContext *ctx = needsActivation ? context->engine->newContext() : &k;
-    ctx->initCallContext(context, Value::nullValue(), this, args, argc);
+    ctx->initCallContext(context, Value::undefinedValue(), this, args, argc);
     Value result = construct(ctx);
     ctx->wireUpPrototype();
     ctx->leaveCallContext();
@@ -464,12 +464,6 @@ Value FunctionObject::call(ExecutionContext *context, Value thisObject, Value *a
     ExecutionContext k;
     ExecutionContext *ctx = needsActivation ? context->engine->newContext() : &k;
 
-    if (!strictMode && !thisObject.isObject()) {
-        if (thisObject.isUndefined() || thisObject.isNull())
-            thisObject = context->engine->globalObject;
-        else
-            thisObject = __qmljs_to_object(thisObject, context);
-    }
     ctx->initCallContext(context, thisObject, this, args, argc);
     Value result = call(ctx);
     ctx->leaveCallContext();
index 53f313f..62e7be4 100644 (file)
@@ -628,9 +628,7 @@ Value __qmljs_get_activation_property(ExecutionContext *ctx, String *name)
 
 Value __qmljs_get_thisObject(ExecutionContext *ctx)
 {
-    if (ctx->thisObject.isObject())
-        return ctx->thisObject;
-    return ctx->engine->globalObject;
+    return ctx->thisObject;
 }
 
 uint __qmljs_equal(Value x, Value y, ExecutionContext *ctx)
index eefd3a3..d9ac31d 100644 (file)
@@ -207,7 +207,8 @@ protected:
     inline void enterEnvironment(Node *node)
     {
         Environment *e = _cg->newEnvironment(node, _env);
-        e->isStrict = _cg->_context->strictMode;
+        if (!e->isStrict)
+            e->isStrict = _cg->_context->strictMode;
         _envStack.append(e);
         _env = e;
     }