summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-07-02 09:17:04 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-07-02 09:17:04 (GMT)
commit4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82 (patch)
treece263441b36155f5b154a895593952b713117c1e
parentce9e05d57a22860b8b29a79d113702102f34659f (diff)
downloadQt-4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82.zip
Qt-4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82.tar.gz
Qt-4518d4d0d8b5842bdc6a7c554b566e0e23e0bf82.tar.bz2
implement QObject property flags
-rw-r--r--src/script/bridge/qscriptqobject.cpp74
-rw-r--r--tests/auto/qscriptqobject/tst_qscriptqobject.cpp25
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");