From 45a83b43ea431a27a7ea05e7e621013dfcfe409a Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 18 Jan 2012 09:50:31 +0100 Subject: [PATCH] Add QJSValue::hasProperty() and hasOwnProperty() functions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Jędrzej Nowacki --- src/declarative/qml/v8/qjsvalue.cpp | 28 +++++++++++- src/declarative/qml/v8/qjsvalue.h | 3 + src/declarative/qml/v8/qjsvalue_impl_p.h | 20 ++++++++ src/declarative/qml/v8/qjsvalue_p.h | 2 + tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp | 51 ++++++++++++++++++++++ tests/auto/declarative/qjsvalue/tst_qjsvalue.h | 4 ++ 6 files changed, 107 insertions(+), 1 deletions(-) diff --git a/src/declarative/qml/v8/qjsvalue.cpp b/src/declarative/qml/v8/qjsvalue.cpp index 7df1d04..9980463 100644 --- a/src/declarative/qml/v8/qjsvalue.cpp +++ b/src/declarative/qml/v8/qjsvalue.cpp @@ -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() diff --git a/src/declarative/qml/v8/qjsvalue.h b/src/declarative/qml/v8/qjsvalue.h index 6dcfe43..756081d 100644 --- a/src/declarative/qml/v8/qjsvalue.h +++ b/src/declarative/qml/v8/qjsvalue.h @@ -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); diff --git a/src/declarative/qml/v8/qjsvalue_impl_p.h b/src/declarative/qml/v8/qjsvalue_impl_p.h index 9e82599..6e1cc4b 100644 --- a/src/declarative/qml/v8/qjsvalue_impl_p.h +++ b/src/declarative/qml/v8/qjsvalue_impl_p.h @@ -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 self(v8::Handle::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 self(v8::Handle::Cast(m_value)); + return self->HasOwnProperty(QJSConverter::toString(name)); +} + inline QJSValue::PropertyFlags QJSValuePrivate::propertyFlags(const QString& name) const { if (!isObject()) diff --git a/src/declarative/qml/v8/qjsvalue_p.h b/src/declarative/qml/v8/qjsvalue_p.h index 3647425..c3677e3 100644 --- a/src/declarative/qml/v8/qjsvalue_p.h +++ b/src/declarative/qml/v8/qjsvalue_p.h @@ -130,6 +130,8 @@ public: template inline QScriptPassPointer 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 name) const; diff --git a/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp b/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp index e3e259d..e8073bc 100644 --- a/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp @@ -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; diff --git a/tests/auto/declarative/qjsvalue/tst_qjsvalue.h b/tests/auto/declarative/qjsvalue/tst_qjsvalue.h index 2e11832..7f7c04a 100644 --- a/tests/auto/declarative/qjsvalue/tst_qjsvalue.h +++ b/tests/auto/declarative/qjsvalue/tst_qjsvalue.h @@ -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(); -- 1.7.2.5