From 9769235a26c3bacc597b994fa249516721833389 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 6 Jul 2009 16:35:32 +0200 Subject: make QScriptClass::HasInstance extension work --- src/script/api/qscriptengine.cpp | 2 +- src/script/api/qscriptvalue.cpp | 2 +- tests/auto/qscriptclass/tst_qscriptclass.cpp | 58 +++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 4321370..87f8e1c 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -424,7 +424,7 @@ bool ClassObject::hasInstance(JSC::ExecState *exec, JSC::JSValue value, JSC::JSV return JSC::JSObject::hasInstance(exec, value, proto); QScriptValueList args; QScriptEnginePrivate *eng_p = static_cast(exec->dynamicGlobalObject())->engine; - args << eng_p->scriptValueFromJSCValue(value) << eng_p->scriptValueFromJSCValue(proto); + args << eng_p->scriptValueFromJSCValue(this) << eng_p->scriptValueFromJSCValue(value); QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args)); return result.toBool(); } diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index ff2823b..bb8b2b7 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -865,7 +865,7 @@ bool QScriptValue::instanceOf(const QScriptValue &other) const QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::JSValue jscProto = eng_p->scriptValueToJSCValue(other.property(QLatin1String("prototype"))); if (!jscProto) - return false; + jscProto = JSC::jsUndefined(); JSC::ExecState *exec = eng_p->globalObject->globalExec(); JSC::JSValue jscOther = eng_p->scriptValueToJSCValue(other); return JSC::asObject(jscOther)->hasInstance(exec, d->jscValue, jscProto); diff --git a/tests/auto/qscriptclass/tst_qscriptclass.cpp b/tests/auto/qscriptclass/tst_qscriptclass.cpp index 6aad73a..963b221 100644 --- a/tests/auto/qscriptclass/tst_qscriptclass.cpp +++ b/tests/auto/qscriptclass/tst_qscriptclass.cpp @@ -149,6 +149,9 @@ public: QScriptString lastPropertyFlagsName() const; uint lastPropertyFlagsId() const; + QScriptClass::Extension lastExtensionType() const; + QVariant lastExtensionArgument() const; + void clearReceivedArgs(); void setIterationEnabled(bool enable); @@ -182,6 +185,9 @@ private: QScriptString m_lastPropertyFlagsName; uint m_lastPropertyFlagsId; + QScriptClass::Extension m_lastExtensionType; + QVariant m_lastExtensionArgument; + QScriptValue m_prototype; bool m_iterationEnabled; CallableMode m_callableMode; @@ -333,6 +339,8 @@ bool TestClass::supportsExtension(Extension extension) const QVariant TestClass::extension(Extension extension, const QVariant &argument) { + m_lastExtensionType = extension; + m_lastExtensionArgument = argument; if (extension == Callable) { Q_ASSERT(m_callableMode != NotCallable); QScriptContext *ctx = qvariant_cast(argument); @@ -354,7 +362,6 @@ QVariant TestClass::extension(Extension extension, } else if (extension == HasInstance) { Q_ASSERT(m_hasInstance); QScriptValueList args = qvariant_cast(argument); - Q_ASSERT(args.size() == 2); QScriptValue obj = args.at(0); QScriptValue value = args.at(1); return value.property("foo").equals(obj.property("foo")); @@ -427,6 +434,16 @@ uint TestClass::lastPropertyFlagsId() const return m_lastPropertyFlagsId; } +QScriptClass::Extension TestClass::lastExtensionType() const +{ + return m_lastExtensionType; +} + +QVariant TestClass::lastExtensionArgument() const +{ + return m_lastExtensionArgument; +} + void TestClass::clearReceivedArgs() { m_lastQueryPropertyObject = QScriptValue(); @@ -445,6 +462,9 @@ void TestClass::clearReceivedArgs() m_lastPropertyFlagsObject = QScriptValue(); m_lastPropertyFlagsName = QScriptString(); m_lastPropertyFlagsId = uint(-1); + + m_lastExtensionType = static_cast(-1); + m_lastExtensionArgument = QVariant(); } void TestClass::setIterationEnabled(bool enable) @@ -627,14 +647,12 @@ void tst_QScriptClass::getAndSetProperty() QVERIFY(cls.lastQueryPropertyName() == s); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(!cls.lastSetPropertyObject().isValid()); - // ### ideally, we should only test for HandlesWriteAccess in this case - QEXPECT_FAIL("", "Doesn't work yet", Continue); - QVERIFY(cls.lastQueryPropertyFlags() == (QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess)); + QVERIFY(cls.lastQueryPropertyFlags() == QScriptClass::HandlesWriteAccess); // re-read property cls.clearReceivedArgs(); QVERIFY(o.property(s).strictlyEquals(num)); - QEXPECT_FAIL("", "Doesn't work yet", Continue); + QEXPECT_FAIL("", "What's the purpose of this check?", Continue); QVERIFY(!cls.lastQueryPropertyObject().isValid()); } } @@ -749,6 +767,11 @@ void tst_QScriptClass::extension() cls.setCallableMode(TestClass::NotCallable); QVERIFY(!cls.supportsExtension(QScriptClass::Callable)); QVERIFY(!cls.supportsExtension(QScriptClass::HasInstance)); + QScriptValue obj = eng.newObject(&cls); + QVERIFY(!obj.call().isValid()); + QCOMPARE((int)cls.lastExtensionType(), -1); + QVERIFY(!obj.instanceOf(obj)); + QCOMPARE((int)cls.lastExtensionType(), -1); } // Callable { @@ -760,22 +783,31 @@ void tst_QScriptClass::extension() obj.setProperty("one", QScriptValue(&eng, 1)); obj.setProperty("two", QScriptValue(&eng, 2)); obj.setProperty("three", QScriptValue(&eng, 3)); + cls.clearReceivedArgs(); { QScriptValueList args; args << QScriptValue(&eng, 4) << QScriptValue(&eng, 5); QScriptValue ret = obj.call(obj, args); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId()); QVERIFY(ret.isNumber()); QCOMPARE(ret.toNumber(), qsreal(15)); } cls.setCallableMode(TestClass::CallableReturnsArgument); + cls.clearReceivedArgs(); { QScriptValue ret = obj.call(obj, QScriptValueList() << 123); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId()); QVERIFY(ret.isNumber()); QCOMPARE(ret.toInt32(), 123); } + cls.clearReceivedArgs(); { QScriptValue ret = obj.call(obj, QScriptValueList() << true); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId()); QVERIFY(ret.isBoolean()); QCOMPARE(ret.toBoolean(), true); } @@ -800,6 +832,15 @@ void tst_QScriptClass::extension() QScriptValue ret = obj.call(obj); QVERIFY(ret.isUndefined()); } + + // construct() + cls.clearReceivedArgs(); + { + QScriptValue ret = obj.construct(); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId()); + QVERIFY(ret.isObject()); + } } // HasInstance { @@ -814,8 +855,15 @@ void tst_QScriptClass::extension() eng.globalObject().setProperty("HasInstanceTester", obj); eng.globalObject().setProperty("hasInstanceValue", plain); + cls.clearReceivedArgs(); { QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::HasInstance); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId()); + QScriptValueList lst = qvariant_cast(cls.lastExtensionArgument()); + QCOMPARE(lst.size(), 2); + QVERIFY(lst.at(0).strictlyEquals(obj)); + QVERIFY(lst.at(1).strictlyEquals(plain)); QVERIFY(ret.isBoolean()); QVERIFY(!ret.toBoolean()); } -- cgit v0.12