Skip to content

Commit

Permalink
Add QJSValue::hasProperty() and hasOwnProperty() functions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kent Hansen authored and Qt by Nokia committed Jan 20, 2012
1 parent b4cd91c commit 45a83b4
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/declarative/qml/v8/qjsvalue.cpp
Expand Up @@ -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
{
Expand Down Expand Up @@ -943,6 +943,32 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
d->setProperty(arrayIndex, QJSValuePrivate::get(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.
Expand Down
3 changes: 3 additions & 0 deletions src/declarative/qml/v8/qjsvalue.h
Expand Up @@ -128,6 +128,9 @@ class Q_DECLARATIVE_EXPORT QJSValue
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);

Expand Down
20 changes: 20 additions & 0 deletions src/declarative/qml/v8/qjsvalue_impl_p.h
Expand Up @@ -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())
Expand Down
2 changes: 2 additions & 0 deletions src/declarative/qml/v8/qjsvalue_p.h
Expand Up @@ -130,6 +130,8 @@ class QJSValuePrivate
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;

Expand Down
51 changes: 51 additions & 0 deletions tests/auto/declarative/qjsvalue/tst_qjsvalue.cpp
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions tests/auto/declarative/qjsvalue/tst_qjsvalue.h
Expand Up @@ -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();
Expand Down

0 comments on commit 45a83b4

Please sign in to comment.