Cleanup call and construct semantics
authorLars Knoll <lars.knoll@digia.com>
Sat, 10 Nov 2012 11:45:00 +0000 (12:45 +0100)
committerLars Knoll <lars.knoll@digia.com>
Sun, 11 Nov 2012 20:24:38 +0000 (21:24 +0100)
Implement proper call() and construct()
methods in FunctionObject, and remove
some duplicated initialization code.

Change-Id: I5c86f9f2cf6e4b65d23d000149db2b79c35538c4
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
qmljs_objects.cpp
qmljs_objects.h
qmljs_runtime.cpp

index 725c5ac..447051f 100644 (file)
@@ -102,7 +102,7 @@ Value Object::__get__(Context *ctx, String *name)
             return Value::undefinedValue();
         FunctionObject *f = p->get->asFunctionObject();
         if (f) {
-            f->call(ctx);
+            f->call(ctx, Value::fromObject(this), 0, 0);
             return ctx->result;
         }
     }
@@ -165,18 +165,10 @@ void Object::__put__(Context *ctx, String *name, const Value &value, bool throwE
         // Clause 5
         if (pd && pd->isAccessor()) {
             assert(pd->set != 0);
-            FunctionObject *func = pd->set->asFunctionObject();
-            assert(func);
 
-            // ### unify with callFunction method
-            Context k;
-            Context *c = func->needsActivation ? ctx->engine->newContext() : &k;
-            Value that = Value::fromObject(this);
             Value args[1];
             args[0] = value;
-            c->initCallContext(ctx, &that, func, args, 1);
-            func->call(c);
-            c->leaveCallContext();
+            pd->set->call(ctx, Value::fromObject(this), args, 1);
             return;
         }
 
@@ -350,6 +342,27 @@ bool FunctionObject::hasInstance(Context *ctx, const Value &value)
     return false;
 }
 
+Value FunctionObject::construct(Context *context, Value *args, int argc)
+{
+    Context k;
+    Context *ctx = needsActivation ? context->engine->newContext() : &k;
+    ctx->initConstructorContext(context, 0, this, args, argc);
+    construct(ctx);
+    ctx->leaveConstructorContext(this);
+    return ctx->result;
+}
+
+Value FunctionObject::call(Context *context, Value thisObject, Value *args, int argc)
+{
+    Context k;
+    Context *ctx = needsActivation ? context->engine->newContext() : &k;
+    const Value *that = thisObject.isUndefined() ? 0 : &thisObject;
+    ctx->initCallContext(context, that, this, args, argc);
+    call(ctx);
+    ctx->leaveCallContext();
+    return ctx->result;
+}
+
 void FunctionObject::call(Context *ctx)
 {
     Q_UNUSED(ctx);
index 1b8a4b9..8cac59d 100644 (file)
@@ -126,8 +126,8 @@ struct PropertyDescriptor {
     union {
         Value value;
         struct {
-            Object *get;
-            Object *set;
+            FunctionObject *get;
+            FunctionObject *set;
         };
     };
     uint type : 8;
@@ -144,7 +144,7 @@ struct PropertyDescriptor {
         pd.configurable = Undefined;
         return pd;
     }
-    static inline PropertyDescriptor fromAccessor(Object *getter, Object *setter) {
+    static inline PropertyDescriptor fromAccessor(FunctionObject *getter, FunctionObject *setter) {
         PropertyDescriptor pd;
         pd.get = getter;
         pd.set = setter;
@@ -480,6 +480,11 @@ struct FunctionObject: Object {
     virtual QString className() { return QStringLiteral("Function"); }
     virtual FunctionObject *asFunctionObject() { return this; }
     virtual bool hasInstance(Context *ctx, const Value &value);
+
+    Value construct(Context *context, Value *args, int argc);
+    Value call(Context *context, Value thisObject, Value *args, int argc);
+
+protected:
     virtual void call(Context *ctx);
     virtual void construct(Context *ctx);
 };
index 3b26daf..16c9402 100644 (file)
@@ -58,13 +58,7 @@ namespace VM {
 static inline Value callFunction(Context *context, Value thisObject, FunctionObject *func, Value *args, int argc)
 {
     if (func) {
-        Context k;
-        Context *ctx = func->needsActivation ? context->engine->newContext() : &k;
-        const Value *that = thisObject.isUndefined() ? 0 : &thisObject;
-        ctx->initCallContext(context, that, func, args, argc);
-        func->call(ctx);
-        ctx->leaveCallContext();
-        return ctx->result;
+        return func->call(context, thisObject, args, argc);
     } else {
         context->throwTypeError();
         return Value::undefinedValue();
@@ -1241,14 +1235,9 @@ Value __qmljs_construct_activation_property(Context *context, String *name, Valu
 
 Value __qmljs_construct_value(Context *context, Value func, Value *args, int argc)
 {
-    if (FunctionObject *f = func.asFunctionObject()) {
-        Context k;
-        Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
-        ctx->initConstructorContext(context, 0, f, args, argc);
-        f->construct(ctx);
-        ctx->leaveConstructorContext(f);
-        return ctx->result;
-    }
+    if (FunctionObject *f = func.asFunctionObject())
+        return f->construct(context, args, argc);
+
     context->throwTypeError();
     return Value::undefinedValue();
 }
@@ -1260,15 +1249,9 @@ Value __qmljs_construct_property(Context *context, Value base, String *name, Val
         thisObject = __qmljs_to_object(base, context);
 
     Value func = thisObject.objectValue()->__get__(context, name);
-    if (FunctionObject *f = func.asFunctionObject()) {
-        Context k;
-        Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
-        ctx->initConstructorContext(context, 0, f, args, argc);
-        ctx->calledAsConstructor = true;
-        f->construct(ctx);
-        ctx->leaveConstructorContext(f);
-        return ctx->result;
-    }
+    if (FunctionObject *f = func.asFunctionObject())
+        return f->construct(context, args, argc);
+
     context->throwTypeError();
     return Value::undefinedValue();
 }