aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-08-08 12:52:56 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-08 15:35:18 +0200
commit0c179baade8f4a57c0f9fe7b48367412e8a41f2a (patch)
tree30c775eda2fcba23827bdfc7f5d4c042813b8a2e /src
parent5046e8898803ab3e83f4dae1260345fdba207a32 (diff)
Fix hasOwnProperty on various types wrapped in QML
* Change semantics of Object::query to not walk the prototype chain but let the caller do that where needed (__hasProperty__) * Re-implement query in various places * Implement method_hasOwnProperty to fall back to query() if getOwnProperty failed * Fix missing prototype initialization in some qml wrappers, as well as missing base class calls to ::get() Change-Id: Ic2a702fd5ff3be2ff3c8317a8a24f99940a9594f Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4object.cpp55
-rw-r--r--src/qml/jsruntime/qv4object_p.h4
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp2
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp4
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp15
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h1
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp19
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h1
8 files changed, 74 insertions, 27 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index edfb535e7a..ad18edd857 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -411,7 +411,30 @@ bool Object::__hasProperty__(String *name) const
{
if (__getPropertyDescriptor__(name))
return true;
- return !query(name).isEmpty();
+
+ const Object *o = this;
+ while (o) {
+ if (!o->query(name).isEmpty())
+ return true;
+ o = o->prototype;
+ }
+
+ return false;
+}
+
+bool Object::__hasProperty__(uint index) const
+{
+ if (__getPropertyDescriptor__(index))
+ return true;
+
+ const Object *o = this;
+ while (o) {
+ if (!o->queryIndexed(index).isEmpty())
+ return true;
+ o = o->prototype;
+ }
+
+ return false;
}
Value Object::get(Managed *m, String *name, bool *hasProperty)
@@ -441,32 +464,26 @@ PropertyAttributes Object::query(const Managed *m, String *name)
return queryIndexed(m, idx);
const Object *o = static_cast<const Object *>(m);
- while (o) {
- uint idx = o->internalClass->find(name);
- if (idx < UINT_MAX)
- return o->internalClass->propertyData[idx];
+ idx = o->internalClass->find(name);
+ if (idx < UINT_MAX)
+ return o->internalClass->propertyData[idx];
- o = o->prototype;
- }
return Attr_Invalid;
}
PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
{
const Object *o = static_cast<const Object *>(m);
- while (o) {
- uint pidx = o->propertyIndexFromArrayIndex(index);
- if (pidx < UINT_MAX) {
- if (o->arrayAttributes)
- return o->arrayAttributes[pidx];
+ uint pidx = o->propertyIndexFromArrayIndex(index);
+ if (pidx < UINT_MAX) {
+ if (o->arrayAttributes)
+ return o->arrayAttributes[pidx];
+ return Attr_Data;
+ }
+ if (o->isStringObject()) {
+ Property *p = static_cast<const StringObject *>(o)->getIndex(index);
+ if (p)
return Attr_Data;
- }
- if (o->isStringObject()) {
- Property *p = static_cast<const StringObject *>(o)->getIndex(index);
- if (p)
- return Attr_Data;
- }
- o = o->prototype;
}
return Attr_Invalid;
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index a9f947b629..ffcca133b7 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -131,9 +131,7 @@ struct Q_QML_EXPORT Object: Managed {
Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
bool __hasProperty__(String *name) const;
- bool __hasProperty__(uint index) const {
- return __getPropertyDescriptor__(index);
- }
+ bool __hasProperty__(uint index) const;
bool __defineOwnProperty__(ExecutionContext *ctx, Property *current, String *member, const Property &p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs);
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 462c9ca81e..fd4afa3a32 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -399,6 +399,8 @@ Value ObjectPrototype::method_hasOwnProperty(SimpleCallContext *ctx)
String *P = ctx->argument(0).toString(ctx);
Object *O = ctx->thisObject.toObject(ctx);
bool r = O->__getOwnProperty__(P) != 0;
+ if (!r)
+ r = !O->query(P).isEmpty();
return Value::fromBoolean(r);
}
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index e396f700af..7afbe3fd29 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -42,6 +42,7 @@
#include "qqmllistwrapper_p.h"
#include <private/qv8engine_p.h>
#include <private/qqmllist_p.h>
+#include <private/qv4objectproto_p.h>
#include <private/qv4functionobject_p.h>
@@ -56,6 +57,7 @@ QmlListWrapper::QmlListWrapper(QV8Engine *engine)
v8(engine)
{
vtbl = &static_vtbl;
+ prototype = QV8Engine::getV4(engine)->objectPrototype;
}
QmlListWrapper::~QmlListWrapper()
@@ -113,7 +115,7 @@ Value QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
if (idx != UINT_MAX)
return getIndexed(m, idx, hasProperty);
- return Value::undefinedValue();
+ return Object::get(m, name, hasProperty);
}
Value QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProperty)
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index f4e9d9b406..20c403c95c 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -157,7 +157,7 @@ Value QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
}
// check for property.
- return QV4::QObjectWrapper::getQmlProperty(v4->current, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision);
+ return QV4::QObjectWrapper::getQmlProperty(v4->current, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
} else if (!siinfo->scriptApi(e).isUndefined()) {
QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine);
// NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
@@ -181,7 +181,7 @@ Value QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
} else if (w->object) {
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
if (ao)
- return QV4::QObjectWrapper::getQmlProperty(v4->current, context, ao, name, QV4::QObjectWrapper::IgnoreRevision);
+ return QV4::QObjectWrapper::getQmlProperty(v4->current, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
// Fall through to base implementation
}
@@ -193,8 +193,7 @@ Value QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
} else if (w->typeNamespace) {
Q_ASSERT(w->importNamespace);
- QQmlTypeNameCache::Result r = w->typeNamespace->query(name,
- w->importNamespace);
+ QQmlTypeNameCache::Result r = w->typeNamespace->query(name, w->importNamespace);
if (r.isValid()) {
QQmlContextData *context = v8engine->callingContext();
@@ -260,6 +259,14 @@ void QmlTypeWrapper::put(Managed *m, String *name, const Value &value)
}
}
+PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name)
+{
+ // ### Implement more efficiently.
+ bool hasProperty = false;
+ const_cast<Managed*>(m)->get(name, &hasProperty);
+ return hasProperty ? Attr_Data : Attr_Invalid;
+}
+
void QmlTypeWrapper::destroy(Managed *that)
{
static_cast<QmlTypeWrapper *>(that)->~QmlTypeWrapper();
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index ae70367dc4..944621b1d6 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -84,6 +84,7 @@ public:
static Value get(Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
+ static PropertyAttributes query(const Managed *, String *name);
static void destroy(Managed *that);
private:
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 05412e99a7..64baf8b1ce 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -201,6 +201,25 @@ bool QmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
return false;
}
+PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, String *name)
+{
+ const QmlValueTypeWrapper *r = m->as<const QmlValueTypeWrapper>();
+ QV4::ExecutionEngine *v4 = m->engine();
+ if (!r)
+ v4->current->throwTypeError();
+
+ QQmlPropertyData local;
+ QQmlPropertyData *result = 0;
+ {
+ QQmlData *ddata = QQmlData::get(r->type, false);
+ if (ddata && ddata->propertyCache)
+ result = ddata->propertyCache->property(name, 0, 0);
+ else
+ result = QQmlPropertyCache::property(r->v8->engine(), r->type, name, 0, local);
+ }
+ return result ? Attr_Data : Attr_Invalid;
+}
+
bool QmlValueTypeWrapper::isEqual(const QVariant& value)
{
if (objectType == QmlValueTypeWrapper::Reference) {
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 18dca0a4c9..f5088a5954 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -87,6 +87,7 @@ public:
static void put(Managed *m, String *name, const Value &value);
static void destroy(Managed *that);
static bool isEqualTo(Managed *m, Managed *other);
+ static PropertyAttributes query(const Managed *, String *name);
static QV4::Value method_toString(SimpleCallContext *ctx);