diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-07-02 09:17:04 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-07-02 09:17:04 (GMT) |
commit | 4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82 (patch) | |
tree | ce263441b36155f5b154a895593952b713117c1e | |
parent | ce9e05d57a22860b8b29a79d113702102f34659f (diff) | |
download | Qt-4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82.zip Qt-4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82.tar.gz Qt-4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82.tar.bz2 |
implement QObject property flags
-rw-r--r-- | src/script/bridge/qscriptqobject.cpp | 74 | ||||
-rw-r--r-- | tests/auto/qscriptqobject/tst_qscriptqobject.cpp | 25 |
2 files changed, 97 insertions, 2 deletions
diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index edfedbb..0162b63 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -142,6 +142,12 @@ static inline QByteArray methodName(const QMetaMethod &method) return signature.left(signature.indexOf('(')); } +static unsigned flagsForMetaProperty(const QMetaProperty &prop) +{ + return (JSC::DontDelete + | (!prop.isWritable() ? unsigned(JSC::ReadOnly) : unsigned(0))); +} + static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str) { QByteArray scope; @@ -1116,6 +1122,74 @@ bool QObjectWrapperObject::getPropertyAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, unsigned &attributes) const { + // ### try to avoid duplicating logic from getOwnPropertySlot() + QByteArray name = qtStringFromJSCUString(propertyName.ustring()).toLatin1(); + QObject *qobject = data->value; + if (!qobject) + return false; + + const QScriptEngine::QObjectWrapOptions &opt = data->options; + const QMetaObject *meta = qobject->metaObject(); + QScriptEnginePrivate *eng = static_cast<QScript::GlobalObject*>(exec->dynamicGlobalObject())->engine; + int index = -1; + if (name.contains('(')) { + QByteArray normalized = QMetaObject::normalizedSignature(name); + if (-1 != (index = meta->indexOfMethod(normalized))) { + QMetaMethod method = meta->method(index); + if (hasMethodAccess(method, index, opt)) { + if (!(opt & QScriptEngine::ExcludeSuperClassMethods) + || (index >= meta->methodOffset())) { + attributes = 0; + if (opt & QScriptEngine::SkipMethodsInEnumeration) + attributes |= JSC::DontEnum; + return true; + } + } + } + } + + index = meta->indexOfProperty(name); + if (index != -1) { + QMetaProperty prop = meta->property(index); + if (prop.isScriptable()) { + if (!(opt & QScriptEngine::ExcludeSuperClassProperties) + || (index >= meta->propertyOffset())) { + attributes = flagsForMetaProperty(prop); + return true; + } + } + } + + index = qobject->dynamicPropertyNames().indexOf(name); + if (index != -1) { + attributes = 0; + return true; + } + + const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods) + ? meta->methodOffset() : 0; + for (index = meta->methodCount() - 1; index >= offset; --index) { + QMetaMethod method = meta->method(index); + if (hasMethodAccess(method, index, opt) + && (methodName(method) == name)) { + attributes = 0; + if (opt & QScriptEngine::SkipMethodsInEnumeration) + attributes |= JSC::DontEnum; + return true; + } + } + + if (!(opt & QScriptEngine::ExcludeChildObjects)) { + QList<QObject*> children = qobject->children(); + for (index = 0; index < children.count(); ++index) { + QObject *child = children.at(index); + if (child->objectName() == qtStringFromJSCUString(propertyName.ustring())) { + attributes = JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum; + return true; + } + } + } + return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); } diff --git a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp index 9fd4eae..eda055c 100644 --- a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp +++ b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp @@ -596,7 +596,6 @@ void tst_QScriptExtQObject::getSetStaticProperty() { QScriptValue mobj = m_engine->globalObject().property("myObject"); QVERIFY(!(mobj.propertyFlags("intProperty") & QScriptValue::ReadOnly)); - QEXPECT_FAIL("", "Flags are wrong", Continue); QVERIFY(mobj.propertyFlags("intProperty") & QScriptValue::Undeletable); QEXPECT_FAIL("", "Flags are wrong", Continue); QVERIFY(mobj.propertyFlags("intProperty") & QScriptValue::PropertyGetter); @@ -611,6 +610,13 @@ void tst_QScriptExtQObject::getSetStaticProperty() QVERIFY(!(mobj.propertyFlags("mySlot") & QScriptValue::SkipInEnumeration)); QEXPECT_FAIL("", "Flags are wrong", Continue); QVERIFY(mobj.propertyFlags("mySlot") & QScriptValue::QObjectMember); + + // signature-based property + QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::ReadOnly)); + QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::Undeletable)); + QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::SkipInEnumeration)); + QEXPECT_FAIL("", "Flags are wrong", Continue); + QVERIFY(mobj.propertyFlags("mySlot()") & QScriptValue::QObjectMember); } // property change in C++ should be reflected in script @@ -790,7 +796,6 @@ void tst_QScriptExtQObject::getSetStaticProperty() QCOMPARE(m_myObject->readOnlyProperty(), 987); { QScriptValue mobj = m_engine->globalObject().property("myObject"); - QEXPECT_FAIL("", "Flags are wrong", Continue); QCOMPARE(mobj.propertyFlags("readOnlyProperty") & QScriptValue::ReadOnly, QScriptValue::ReadOnly); } @@ -859,6 +864,9 @@ void tst_QScriptExtQObject::getSetStaticProperty() QScriptValue sameSlot = m_engine->evaluate("myObject.mySlot"); QEXPECT_FAIL("", "Slot wrappers aren't persistent yet", Continue); QVERIFY(sameSlot.strictlyEquals(slot)); + sameSlot = m_engine->evaluate("myObject[mySlot()]"); + QEXPECT_FAIL("", "Slot wrappers aren't persistent yet", Continue); + QVERIFY(sameSlot.strictlyEquals(slot)); } } @@ -900,6 +908,8 @@ void tst_QScriptExtQObject::getSetDynamicProperty() void tst_QScriptExtQObject::getSetChildren() { + QScriptValue mobj = m_engine->evaluate("myObject"); + // initially the object does not have the child QCOMPARE(m_engine->evaluate("myObject.hasOwnProperty('child')") .strictlyEquals(QScriptValue(m_engine, false)), true); @@ -910,6 +920,17 @@ void tst_QScriptExtQObject::getSetChildren() QCOMPARE(m_engine->evaluate("myObject.hasOwnProperty('child')") .strictlyEquals(QScriptValue(m_engine, true)), true); + QVERIFY(mobj.propertyFlags("child") & QScriptValue::ReadOnly); + QVERIFY(mobj.propertyFlags("child") & QScriptValue::Undeletable); + QVERIFY(mobj.propertyFlags("child") & QScriptValue::SkipInEnumeration); + QVERIFY(!(mobj.propertyFlags("child") & QScriptValue::QObjectMember)); + + { + QScriptValue scriptChild = m_engine->evaluate("myObject.child"); + QVERIFY(scriptChild.isQObject()); + QCOMPARE(scriptChild.toQObject(), (QObject*)child); + } + // add a grandchild MyQObject *grandChild = new MyQObject(child); grandChild->setObjectName("grandChild"); |