From d9b959c85b1b285e63e8aa2dcc01ac0426614ddf Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 9 Jul 2009 13:00:02 +0200 Subject: make native object constructors work With commit 6985212c8909c89183b232ca28b96a2c8a2f1385, context->thisObject() now returns the right thing. --- src/script/bridge/qscriptfunction.cpp | 18 ++++++------ tests/auto/qscriptvalue/tst_qscriptvalue.cpp | 42 ++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp index c93e025..8d2f0c8 100644 --- a/src/script/bridge/qscriptfunction.cpp +++ b/src/script/bridge/qscriptfunction.cpp @@ -70,19 +70,17 @@ JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObje const JSC::ArgList &args) { FunctionWrapper *self = static_cast(callee); - QScriptValue object = self->data->engine->newObject(); QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(self->data->engine); JSC::ExecState *previousFrame = eng_p->currentFrame; QScriptContext *ctx = eng_p->contextForFrame(exec); eng_p->currentFrame = exec; + QScriptValue defaultObject = ctx->thisObject(); QScriptValue result = self->data->function(ctx, self->data->engine); - if (!result.isValid()) - result = QScriptValue(QScriptValue::UndefinedValue); + if (!result.isObject()) + result = defaultObject; eng_p->currentFrame = previousFrame; eng_p->releaseContextForFrame(exec); - if (result.isObject()) - return JSC::asObject(eng_p->scriptValueToJSCValue(result)); - return JSC::asObject(eng_p->scriptValueToJSCValue(object)); + return JSC::asObject(eng_p->scriptValueToJSCValue(result)); } FunctionWithArgWrapper::FunctionWithArgWrapper(QScriptEngine *engine, int length, const JSC::Identifier &name, @@ -124,17 +122,17 @@ JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC: const JSC::ArgList &args) { FunctionWithArgWrapper *self = static_cast(callee); - QScriptValue object = self->data->engine->newObject(); QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(self->data->engine); JSC::ExecState *previousFrame = eng_p->currentFrame; QScriptContext *ctx = eng_p->contextForFrame(exec); eng_p->currentFrame = exec; + QScriptValue defaultObject = ctx->thisObject(); QScriptValue result = self->data->function(ctx, self->data->engine, self->data->arg); + if (!result.isObject()) + result = defaultObject; eng_p->currentFrame = previousFrame; eng_p->releaseContextForFrame(exec); - if (result.isObject()) - return JSC::asObject(eng_p->scriptValueToJSCValue(result)); - return JSC::asObject(eng_p->scriptValueToJSCValue(object)); + return JSC::asObject(eng_p->scriptValueToJSCValue(result)); } } // namespace QScript diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index 9ad47cf..06f1ec6 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2525,18 +2525,56 @@ void tst_QScriptValue::call() } } +static QScriptValue ctorReturningUndefined(QScriptContext *ctx, QScriptEngine *) +{ + ctx->thisObject().setProperty("foo", 123); + return QScriptValue(QScriptValue::UndefinedValue); +} + +static QScriptValue ctorReturningNewObject(QScriptContext *, QScriptEngine *eng) +{ + QScriptValue result = eng->newObject(); + result.setProperty("bar", 456); + return result; +} + void tst_QScriptValue::construct() { QScriptEngine eng; { - QScriptValue fun = eng.evaluate("function () { }"); + QScriptValue fun = eng.evaluate("function () { this.foo = 123; }"); QEXPECT_FAIL("", "JSC parser doesn't understand function expressions", Continue); QVERIFY(fun.isFunction()); - fun = eng.evaluate("(function () { })"); + fun = eng.evaluate("(function () { this.foo = 123; })"); QScriptValue ret = fun.construct(); QVERIFY(ret.isObject()); QVERIFY(ret.instanceOf(fun)); + QCOMPARE(ret.property("foo").toInt32(), 123); + } + // returning a different object overrides the default-constructed one + { + QScriptValue fun = eng.evaluate("(function () { return { bar: 456 }; })"); + QVERIFY(fun.isFunction()); + QScriptValue ret = fun.construct(); + QVERIFY(ret.isObject()); + QVERIFY(!ret.instanceOf(fun)); + QCOMPARE(ret.property("bar").toInt32(), 456); + } + + { + QScriptValue fun = eng.newFunction(ctorReturningUndefined); + QScriptValue ret = fun.construct(); + QVERIFY(ret.isObject()); + QVERIFY(ret.instanceOf(fun)); + QCOMPARE(ret.property("foo").toInt32(), 123); + } + { + QScriptValue fun = eng.newFunction(ctorReturningNewObject); + QScriptValue ret = fun.construct(); + QVERIFY(ret.isObject()); + QVERIFY(!ret.instanceOf(fun)); + QCOMPARE(ret.property("bar").toInt32(), 456); } QScriptValue Number = eng.evaluate("Number"); -- cgit v0.12