Add QJSValue::hasProperty() and hasOwnProperty() functions
authorKent Hansen <kent.hansen@nokia.com>
Wed, 18 Jan 2012 08:50:31 +0000 (09:50 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 20 Jan 2012 22:35:18 +0000 (23:35 +0100)
These functions provide a way of querying whether a property exists,
without relying on the QJSValue invalid type (which will be removed).

Task-number: QTBUG-23604
Change-Id: I2efd53a1e54cc202ecc022d12730b2775384cf53
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com>
src/declarative/qml/v8/qjsvalue.cpp
src/declarative/qml/v8/qjsvalue.h
src/declarative/qml/v8/qjsvalue_impl_p.h
src/declarative/qml/v8/qjsvalue_p.h
tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp
tests/auto/declarative/qjsvalue/tst_qjsvalue.h

index 7df1d04..9980463 100644 (file)
@@ -866,7 +866,7 @@ bool QJSValue::instanceOf(const QJSValue &other) const
   occurred, property() returns the value that was thrown (typically
   an \c{Error} object).
 
-  \sa setProperty(), propertyFlags(), QJSValueIterator
+  \sa setProperty(), hasProperty(), QJSValueIterator
 */
 QJSValue QJSValue::property(const QString& name) const
 {
@@ -944,6 +944,32 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
 }
 
 /*!
+  Returns true if this object has a property of the given \a name,
+  otherwise returns false.
+
+  \sa property(), hasOwnProperty()
+*/
+bool QJSValue::hasProperty(const QString &name) const
+{
+    Q_D(const QJSValue);
+    QScriptIsolate api(d->engine());
+    return d->hasProperty(name);
+}
+
+/*!
+  Returns true if this object has an own (not prototype-inherited)
+  property of the given \a name, otherwise returns false.
+
+  \sa property(), hasProperty()
+*/
+bool QJSValue::hasOwnProperty(const QString &name) const
+{
+    Q_D(const QJSValue);
+    QScriptIsolate api(d->engine());
+    return d->hasOwnProperty(name);
+}
+
+/*!
   Returns the flags of the property with the given \a name.
 
   \sa property()
index 6dcfe43..756081d 100644 (file)
@@ -128,6 +128,9 @@ public:
     QJSValue property(const QString &name) const;
     void setProperty(const QString &name, const QJSValue &value);
 
+    bool hasProperty(const QString &name) const;
+    bool hasOwnProperty(const QString &name) const;
+
     QJSValue property(quint32 arrayIndex) const;
     void setProperty(quint32 arrayIndex, const QJSValue &value);
 
index 9e82599..6e1cc4b 100644 (file)
@@ -880,6 +880,26 @@ inline bool QJSValuePrivate::deleteProperty(const QString& name)
     return self->Delete(QJSConverter::toString(name));
 }
 
+inline bool QJSValuePrivate::hasProperty(const QString &name) const
+{
+    if (!isObject())
+        return false;
+
+    v8::HandleScope handleScope;
+    v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value));
+    return self->Has(QJSConverter::toString(name));
+}
+
+inline bool QJSValuePrivate::hasOwnProperty(const QString &name) const
+{
+    if (!isObject())
+        return false;
+
+    v8::HandleScope handleScope;
+    v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value));
+    return self->HasOwnProperty(QJSConverter::toString(name));
+}
+
 inline QJSValue::PropertyFlags QJSValuePrivate::propertyFlags(const QString& name) const
 {
     if (!isObject())
index 3647425..c3677e3 100644 (file)
@@ -130,6 +130,8 @@ public:
     template<typename T>
     inline QScriptPassPointer<QJSValuePrivate> property(T name) const;
     inline bool deleteProperty(const QString& name);
+    inline bool hasProperty(const QString &name) const;
+    inline bool hasOwnProperty(const QString &name) const;
     inline QJSValue::PropertyFlags propertyFlags(const QString& name) const;
     inline QJSValue::PropertyFlags propertyFlags(v8::Handle<v8::String> name) const;
 
index e3e259d..e8073bc 100644 (file)
@@ -1792,6 +1792,57 @@ static QJSValue getSet__proto__(QScriptContext *ctx, QScriptEngine *)
 }
 #endif
 
+void tst_QJSValue::hasProperty_basic()
+{
+    QJSEngine eng;
+    QJSValue obj = eng.newObject();
+    QVERIFY(obj.hasProperty("hasOwnProperty")); // inherited from Object.prototype
+    QVERIFY(!obj.hasOwnProperty("hasOwnProperty"));
+
+    QVERIFY(!obj.hasProperty("foo"));
+    QVERIFY(!obj.hasOwnProperty("foo"));
+    obj.setProperty("foo", 123);
+    QVERIFY(obj.hasProperty("foo"));
+    QVERIFY(obj.hasOwnProperty("foo"));
+
+    QVERIFY(!obj.hasProperty("bar"));
+    QVERIFY(!obj.hasOwnProperty("bar"));
+}
+
+void tst_QJSValue::hasProperty_globalObject()
+{
+    QJSEngine eng;
+    QJSValue global = eng.globalObject();
+    QVERIFY(global.hasProperty("Math"));
+    QVERIFY(global.hasOwnProperty("Math"));
+    QVERIFY(!global.hasProperty("NoSuchStandardProperty"));
+    QVERIFY(!global.hasOwnProperty("NoSuchStandardProperty"));
+
+    QVERIFY(!global.hasProperty("foo"));
+    QVERIFY(!global.hasOwnProperty("foo"));
+    global.setProperty("foo", 123);
+    QVERIFY(global.hasProperty("foo"));
+    QVERIFY(global.hasOwnProperty("foo"));
+}
+
+void tst_QJSValue::hasProperty_changePrototype()
+{
+    QJSEngine eng;
+    QJSValue obj = eng.newObject();
+    QJSValue proto = eng.newObject();
+    obj.setPrototype(proto);
+
+    QVERIFY(!obj.hasProperty("foo"));
+    QVERIFY(!obj.hasOwnProperty("foo"));
+    proto.setProperty("foo", 123);
+    QVERIFY(obj.hasProperty("foo"));
+    QVERIFY(!obj.hasOwnProperty("foo"));
+
+    obj.setProperty("foo", 456); // override prototype property
+    QVERIFY(obj.hasProperty("foo"));
+    QVERIFY(obj.hasOwnProperty("foo"));
+}
+
 void tst_QJSValue::getSetProperty_HooliganTask162051()
 {
     QJSEngine eng;
index 2e11832..7f7c04a 100644 (file)
@@ -113,6 +113,10 @@ private slots:
     void equals();
     void strictlyEquals();
 
+    void hasProperty_basic();
+    void hasProperty_globalObject();
+    void hasProperty_changePrototype();
+
     void getSetPrototype_cyclicPrototype();
     void getSetPrototype_evalCyclicPrototype();
     void getSetPrototype_eval();