aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-17 22:06:45 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-25 07:36:22 +0000
commit3e1bb90da4c44455c8c307e01876cc2127bdb15c (patch)
tree6b9278e2612fe71ce84273857babf8494b8d91bc
parentf5a7953df3cb61edc6cc30175ea4f7f1c97deae6 (diff)
Implement a virtual interface for getOwnProperty
This is required to support Proxy properly, and at the same time fixes a couple of test failures. The new interface also replaces the old query and queryIndexed virtual interfaces, as those where doing a subset of what getOwnProperty does. Change-Id: I750e366b475ce971d6d9edf35fa17b7a2b07f771 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsapi/qjsvalue.cpp2
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4context.cpp2
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp10
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h3
-rw-r--r--src/qml/jsruntime/qv4object.cpp146
-rw-r--r--src/qml/jsruntime/qv4object_p.h21
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp4
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp13
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp9
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp38
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4string.cpp8
-rw-r--r--src/qml/jsruntime/qv4string_p.h2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp3
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp19
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp18
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h2
21 files changed, 135 insertions, 191 deletions
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 348ddb25d9..63b10adf2b 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -1291,7 +1291,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasOwnProperty(s);
+ return o->getOwnProperty(s->identifier()) != Attr_Invalid;
}
/*!
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 58951d043c..3fa680bfef 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -202,19 +202,19 @@ bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
return Object::deleteIndexedProperty(m, index);
}
-PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
+PropertyAttributes ArgumentsObject::getOwnProperty(Managed *m, Identifier id, Property *p)
{
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- if (args->fullyCreated())
- return Object::queryIndexed(m, index);
+ if (!id.isArrayIndex() || args->fullyCreated())
+ return Object::getOwnProperty(m, id, p);
- uint numAccessors = qMin(args->d()->nFormals, args->context()->argc());
+ uint index = id.asArrayIndex();
uint argCount = args->context()->argc();
if (index >= argCount)
return PropertyAttributes();
- if (index >= numAccessors)
- return Attr_Data;
- return Attr_Accessor;
+ if (p)
+ p->value = args->context()->args()[index];
+ return Attr_Data;
}
DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction);
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index f246f66019..2518b4642a 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -150,7 +150,7 @@ struct ArgumentsObject: Object {
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static bool putIndexed(Managed *m, uint index, const Value &value);
static bool deleteIndexedProperty(Managed *m, uint index);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static qint64 getLength(const Managed *m);
void fullyCreate();
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 434f6781a8..a82628e249 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -247,7 +247,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
mappedValue = *nextValue;
}
- if (!a->hasOwnProperty(k)) {
+ if (a->getOwnProperty(Identifier::fromArrayIndex(k)) == Attr_Invalid) {
a->arraySet(k, mappedValue);
} else {
// Don't return: we need to close the iterator.
@@ -289,7 +289,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
mappedValue = kValue;
}
- if (a->hasOwnProperty(k))
+ if (a->getOwnProperty(Identifier::fromArrayIndex(k)) != Attr_Invalid)
return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
a->arraySet(k, mappedValue);
@@ -318,7 +318,7 @@ ReturnedValue ArrayPrototype::method_of(const FunctionObject *builtin, const Val
int k = 0;
while (k < argc) {
- if (a->hasOwnProperty(k)) {
+ if (a->getOwnProperty(Identifier::fromArrayIndex(k)) != Attr_Invalid) {
return scope.engine->throwTypeError(QString::fromLatin1("Cannot redefine property: %1").arg(k));
}
a->arraySet(k, argv[k]);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 78cca8d525..61657477b0 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -178,7 +178,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
ctx = ctx->d()->outer;
}
- if (activation->hasOwnProperty(name))
+ if (activation->getOwnProperty(name->toPropertyKey()) != Attr_Invalid)
return;
ScopedProperty desc(scope);
PropertyAttributes attrs(Attr_Data);
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 4bfae14aec..08e480e8c2 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -44,6 +44,16 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+bool Identifier::isString() const
+{
+ return isValid() && asHeapObject()->internalClass->vtable->isString;
+}
+
+bool Identifier::isSymbol() const
+{
+ return isValid() && !asHeapObject()->internalClass->vtable->isString && asHeapObject()->internalClass->vtable->isStringOrSymbol;
+}
+
QString Identifier::toQString() const
{
if (isArrayIndex())
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index b167a149a2..fd4ff75974 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -73,6 +73,9 @@ struct Identifier
static Identifier fromHeapObject(Heap::Base *b) { return Identifier{ reinterpret_cast<quintptr>(b) }; }
Heap::Base *asHeapObject() const { return (id & 1) ? nullptr : reinterpret_cast<Heap::Base *>(id); }
+ bool isString() const;
+ bool isSymbol() const;
+
Q_QML_EXPORT QString toQString() const;
bool operator ==(const Identifier &other) const { return id == other.id; }
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 516e9b3c65..50ffd6fae0 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -278,50 +278,6 @@ void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttribut
}
}
-// Section 8.12.1
-void Object::getOwnProperty(StringOrSymbol *name, PropertyAttributes *attrs, Property *p)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return getOwnProperty(idx, attrs, p);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- uint member = internalClass()->find(id);
- if (member < UINT_MAX) {
- *attrs = internalClass()->propertyData[member];
- if (p) {
- p->value = *propertyData(member);
- if (attrs->isAccessor())
- p->set = *propertyData(member + SetterOffset);
- }
- return;
- }
-
- if (attrs)
- *attrs = Attr_Invalid;
- return;
-}
-
-void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p)
-{
- if (arrayData()) {
- if (arrayData()->getProperty(index, p, attrs))
- return;
- }
- if (isStringObject()) {
- *attrs = Attr_NotConfigurable|Attr_NotWritable;
- if (p)
- p->value = static_cast<StringObject *>(this)->getIndex(index);
- return;
- }
-
- if (attrs)
- *attrs = Attr_Invalid;
- return;
-}
-
// Section 8.12.2
PropertyIndex Object::getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs)
{
@@ -378,7 +334,7 @@ bool Object::hasProperty(StringOrSymbol *name) const
Scope scope(engine());
ScopedObject o(scope, d());
while (o) {
- if (o->hasOwnProperty(name))
+ if (o->getOwnProperty(name->toPropertyKey()) != Attr_Invalid)
return true;
o = o->prototype();
@@ -392,8 +348,8 @@ bool Object::hasProperty(uint index) const
Scope scope(engine());
ScopedObject o(scope, d());
while (o) {
- if (o->hasOwnProperty(index))
- return true;
+ if (o->getOwnProperty(Identifier::fromArrayIndex(index)) != Attr_Invalid)
+ return true;
o = o->prototype();
}
@@ -401,36 +357,6 @@ bool Object::hasProperty(uint index) const
return false;
}
-bool Object::hasOwnProperty(StringOrSymbol *name) const
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return hasOwnProperty(idx);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- if (internalClass()->find(id) < UINT_MAX)
- return true;
- if (!query(name).isEmpty())
- return true;
- return false;
-}
-
-bool Object::hasOwnProperty(uint index) const
-{
- if (arrayData() && !arrayData()->isEmpty(index))
- return true;
-
- if (isStringObject()) {
- if (index < static_cast<const StringObject *>(this)->length())
- return true;
- }
- if (!queryIndexed(index).isEmpty())
- return true;
- return false;
-}
-
ReturnedValue Object::callAsConstructor(const FunctionObject *f, const Value *, int)
{
return f->engine()->throwTypeError();
@@ -461,36 +387,6 @@ bool Object::putIndexed(Managed *m, uint index, const Value &value)
return static_cast<Object *>(m)->internalPutIndexed(index, value);
}
-PropertyAttributes Object::query(const Managed *m, StringOrSymbol *name)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return queryIndexed(m, idx);
-
- name->makeIdentifier();
- Identifier id = name->identifier();
-
- const Object *o = static_cast<const Object *>(m);
- idx = o->internalClass()->find(id);
- if (idx < UINT_MAX)
- return o->internalClass()->propertyData[idx];
-
- return Attr_Invalid;
-}
-
-PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
-{
- const Object *o = static_cast<const Object *>(m);
- if (o->arrayData() && !o->arrayData()->isEmpty(index))
- return o->arrayData()->attributes(index);
-
- if (o->isStringObject()) {
- if (index < static_cast<const StringObject *>(o)->length())
- return (Attr_NotWritable|Attr_NotConfigurable);
- }
- return Attr_Invalid;
-}
-
bool Object::deleteProperty(Managed *m, StringOrSymbol *name)
{
return static_cast<Object *>(m)->internalDeleteProperty(name);
@@ -1105,6 +1001,42 @@ ReturnedValue Object::instanceOf(const Object *typeObject, const Value &var)
return Encode(false);
}
+PropertyAttributes Object::getOwnProperty(Managed *m, Identifier id, Property *p)
+{
+ PropertyAttributes attrs;
+ Object *o = static_cast<Object *>(m);
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ if (o->arrayData()) {
+ if (o->arrayData()->getProperty(index, p, &attrs))
+ return attrs;
+ }
+ if (o->isStringObject()) {
+ if (index >= static_cast<const StringObject *>(m)->length())
+ return Attr_Invalid;
+ attrs = Attr_NotConfigurable|Attr_NotWritable;
+ if (p)
+ p->value = static_cast<StringObject *>(o)->getIndex(index);
+ return attrs;
+ }
+ } else {
+ Q_ASSERT(id.asHeapObject());
+
+ uint member = o->internalClass()->find(id);
+ if (member < UINT_MAX) {
+ attrs = o->internalClass()->propertyData[member];
+ if (p) {
+ p->value = *o->propertyData(member);
+ if (attrs.isAccessor())
+ p->set = *o->propertyData(member + SetterOffset);
+ }
+ return attrs;
+ }
+ }
+
+ return Attr_Invalid;
+}
+
bool Object::setArrayLength(uint newLen)
{
Q_ASSERT(isArrayObject());
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 5ad67635db..a08ea851cd 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -173,10 +173,9 @@ struct ObjectVTable
ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty);
bool (*put)(Managed *, StringOrSymbol *name, const Value &value);
bool (*putIndexed)(Managed *, uint index, const Value &value);
- PropertyAttributes (*query)(const Managed *, StringOrSymbol *name);
- PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, StringOrSymbol *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
+ PropertyAttributes (*getOwnProperty)(Managed *m, Identifier id, Property *p);
qint64 (*getLength)(const Managed *m);
void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
ReturnedValue (*instanceOf)(const Object *typeObject, const Value &var);
@@ -192,10 +191,9 @@ const QV4::ObjectVTable classname::static_vtbl = \
getIndexed, \
put, \
putIndexed, \
- query, \
- queryIndexed, \
deleteProperty, \
deleteIndexedProperty, \
+ getOwnProperty, \
getLength, \
advanceIterator, \
instanceOf \
@@ -243,8 +241,9 @@ struct Q_QML_EXPORT Object: Managed {
Heap::Object *prototype() const { return d()->prototype(); }
bool setPrototype(Object *proto);
- void getOwnProperty(StringOrSymbol *name, PropertyAttributes *attrs, Property *p = nullptr);
- void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = nullptr);
+ PropertyAttributes getOwnProperty(Identifier id, Property *p = nullptr) {
+ return vtable()->getOwnProperty(this, id, p);
+ }
PropertyIndex getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs);
PropertyIndex getValueOrSetter(uint index, PropertyAttributes *attrs);
@@ -252,9 +251,6 @@ struct Q_QML_EXPORT Object: Managed {
bool hasProperty(StringOrSymbol *name) const;
bool hasProperty(uint index) const;
- bool hasOwnProperty(StringOrSymbol *name) const;
- bool hasOwnProperty(uint index) const;
-
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionEngine *engine, StringOrSymbol *name, const Property *p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
@@ -418,10 +414,6 @@ public:
return ret;
}
- PropertyAttributes query(StringOrSymbol *name) const
- { return vtable()->query(this, name); }
- PropertyAttributes queryIndexed(uint index) const
- { return vtable()->queryIndexed(this, index); }
bool deleteProperty(StringOrSymbol *name)
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
@@ -439,10 +431,9 @@ protected:
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
static bool putIndexed(Managed *m, uint index, const Value &value);
- static PropertyAttributes query(const Managed *m, StringOrSymbol *name);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, StringOrSymbol *name);
static bool deleteIndexedProperty(Managed *m, uint index);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static qint64 getLength(const Managed *m);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 1290a2c1b2..109e189ede 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -104,8 +104,8 @@ void ObjectIterator::next(Value *name, uint *index, Property *pd, PropertyAttrib
n = *name;
bool shadowed = false;
while (o->d() != current->heapObject()) {
- if ((!!n && o->hasOwnProperty(n)) ||
- (*index != UINT_MAX && o->hasOwnProperty(*index))) {
+ Identifier id = n ? (n->makeIdentifier(), n->identifier()) : Identifier::fromArrayIndex(*index);
+ if ((id.isValid() ||id.isArrayIndex()) && o->getOwnProperty(id) != Attr_Invalid) {
shadowed = true;
break;
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index a61b5d5136..8525ad9438 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -167,9 +167,8 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObj
if (scope.engine->hasException)
return QV4::Encode::undefined();
- PropertyAttributes attrs;
ScopedProperty desc(scope);
- O->getOwnProperty(name, &attrs, desc);
+ PropertyAttributes attrs = O->getOwnProperty(name->toPropertyKey(), desc);
return fromPropertyDescriptor(scope.engine, desc, attrs);
}
@@ -237,9 +236,8 @@ ReturnedValue ObjectPrototype::method_assign(const FunctionObject *b, const Valu
for (quint32 i = 0; i < length; ++i) {
nextKey = Value::fromReturnedValue(keys->getIndexed(i)).toString(scope.engine);
- PropertyAttributes attrs;
ScopedProperty prop(scope);
- from->getOwnProperty(nextKey, &attrs, prop);
+ PropertyAttributes attrs = from->getOwnProperty(nextKey->toPropertyKey(), prop);
if (attrs == PropertyFlag::Attr_Invalid)
continue;
@@ -592,9 +590,7 @@ ReturnedValue ObjectPrototype::method_hasOwnProperty(const FunctionObject *b, co
ScopedObject O(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- bool r = O->hasOwnProperty(P);
- if (!r)
- r = !O->query(P).isEmpty();
+ bool r = O->getOwnProperty(P->toPropertyKey()) != Attr_Invalid;
return Encode(r);
}
@@ -627,8 +623,7 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(const FunctionObject
ScopedObject o(scope, thisObject->toObject(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
- PropertyAttributes attrs;
- o->getOwnProperty(p, &attrs);
+ PropertyAttributes attrs = o->getOwnProperty(p->toPropertyKey());
return Encode(attrs.isEnumerable());
}
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index b34af97870..11000123f6 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -81,8 +81,7 @@ ReturnedValue ProxyObject::get(const Managed *m, StringOrSymbol *name, bool *has
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
ScopedProperty targetDesc(scope);
- PropertyAttributes attributes;
- target->getOwnProperty(name, &attributes, targetDesc);
+ PropertyAttributes attributes = target->getOwnProperty(name->toPropertyKey(), targetDesc);
if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
if (attributes.isData() && !attributes.isWritable()) {
if (!trapResult->sameValue(targetDesc->value))
@@ -131,8 +130,7 @@ bool ProxyObject::put(Managed *m, StringOrSymbol *name, const Value &value)
if (!trapResult->toBoolean())
return false;
ScopedProperty targetDesc(scope);
- PropertyAttributes attributes;
- target->getOwnProperty(name, &attributes, targetDesc);
+ PropertyAttributes attributes = target->getOwnProperty(name->toPropertyKey(), targetDesc);
if (attributes != Attr_Invalid && !attributes.isConfigurable()) {
if (attributes.isData() && !attributes.isWritable()) {
if (!value.sameValue(targetDesc->value))
@@ -179,8 +177,7 @@ bool ProxyObject::deleteProperty(Managed *m, StringOrSymbol *name)
if (!trapResult->toBoolean())
return false;
ScopedProperty targetDesc(scope);
- PropertyAttributes attributes;
- target->getOwnProperty(name, &attributes, targetDesc);
+ PropertyAttributes attributes = target->getOwnProperty(name->toPropertyKey(), targetDesc);
if (attributes == Attr_Invalid)
return true;
if (!attributes.isConfigurable())
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e17ce55f7b..2ab77502d6 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -733,25 +733,29 @@ bool QObjectWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
return true;
}
-PropertyAttributes QObjectWrapper::query(const Managed *m, StringOrSymbol *name)
+PropertyAttributes QObjectWrapper::getOwnProperty(Managed *m, Identifier id, Property *p)
{
- if (name->isSymbol())
- return QV4::Object::query(m, name);
- String *n = static_cast<String *>(name);
-
- const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
- const QObject *thatObject = that->d()->object();
- if (QQmlData::wasDeleted(thatObject))
- return QV4::Object::query(m, name);
+ if (id.isString()) {
+ QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
+ const QObject *thatObject = that->d()->object();
+ if (!QQmlData::wasDeleted(thatObject)) {
+ Scope scope(m);
+ ScopedString n(scope, id.asHeapObject());
+ QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlPropertyData local;
+ if (that->findProperty(scope.engine, qmlContext, n, IgnoreRevision, &local)
+ || n->equals(scope.engine->id_destroy()) || n->equals(scope.engine->id_toString())) {
+ if (p) {
+ // ### probably not the fastest implementation
+ bool hasProperty;
+ p->value = that->getQmlProperty(qmlContext, n, IgnoreRevision, &hasProperty, /*includeImports*/ true);
+ }
+ return QV4::Attr_Data;
+ }
+ }
+ }
- ExecutionEngine *engine = that->engine();
- QQmlContextData *qmlContext = engine->callingQmlContext();
- QQmlPropertyData local;
- if (that->findProperty(engine, qmlContext, n, IgnoreRevision, &local)
- || n->equals(engine->id_destroy()) || n->equals(engine->id_toString()))
- return QV4::Attr_Data;
- else
- return QV4::Object::query(m, name);
+ return QV4::Object::getOwnProperty(m, id, p);
}
void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 56e20adbfa..12272c2925 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -195,7 +195,7 @@ protected:
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
- static PropertyAttributes query(const Managed *, StringOrSymbol *name);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_connect(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 27c73a2b77..cfd2d0a5b2 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -250,6 +250,14 @@ void Heap::StringOrSymbol::createHashValue() const
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
}
+Identifier StringOrSymbol::toPropertyKey() const {
+ uint index = asArrayIndex();
+ if (index < UINT_MAX)
+ return Identifier::fromArrayIndex(index);
+ makeIdentifier();
+ return identifier();
+}
+
uint String::getLength(const Managed *m)
{
return static_cast<const String *>(m)->d()->length();
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 0deb542ea2..2e3ca977bf 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -178,6 +178,8 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : public Managed {
uint asArrayIndex() const;
+ Identifier toPropertyKey() const;
+
inline QString toQString() const {
return d()->toQString();
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 3639edac17..d35012d11e 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -118,9 +118,8 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name,
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
++it->arrayIndex;
- PropertyAttributes a;
Property pd;
- s->getOwnProperty(*index, &a, &pd);
+ PropertyAttributes a = s->getOwnProperty(Identifier::fromArrayIndex(*index), &pd);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
p->copy(&pd, a);
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 7270cffb00..144d077c44 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -350,15 +350,18 @@ bool QQmlTypeWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
return false;
}
-PropertyAttributes QQmlTypeWrapper::query(const Managed *m, StringOrSymbol *name)
+PropertyAttributes QQmlTypeWrapper::getOwnProperty(Managed *m, Identifier id, Property *p)
{
- if (name->isSymbol())
- return Object::query(m, name);
- String *n = static_cast<String *>(name);
- // ### Implement more efficiently.
- bool hasProperty = false;
- static_cast<Object *>(const_cast<Managed*>(m))->get(n, &hasProperty);
- return hasProperty ? Attr_Data : Attr_Invalid;
+ if (id.isString()) {
+ Scope scope(m);
+ ScopedString n(scope, id.asHeapObject());
+ // ### Implement more efficiently.
+ bool hasProperty = false;
+ static_cast<Object *>(m)->get(n, &hasProperty);
+ return hasProperty ? Attr_Data : Attr_Invalid;
+ }
+
+ return QV4::Object::getOwnProperty(m, id, p);
}
bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 30bbc8d179..b17d0e0868 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -114,7 +114,7 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
- static PropertyAttributes query(const Managed *, StringOrSymbol *name);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static bool isEqualTo(Managed *that, Managed *o);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
};
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 7e0cf64bed..aa716b8a73 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -241,17 +241,17 @@ bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
return false;
}
-PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, StringOrSymbol *name)
+PropertyAttributes QQmlValueTypeWrapper::getOwnProperty(Managed *m, Identifier id, Property *p)
{
- if (name->isSymbol())
- return Object::query(m, name);
-
- String *n = static_cast<String *>(name);
- Q_ASSERT(m->as<const QQmlValueTypeWrapper>());
- const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+ if (id.isString()) {
+ Scope scope(m);
+ ScopedString n(scope, id.asHeapObject());
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(n.getPointer(), nullptr, nullptr);
+ return result ? Attr_Data : Attr_Invalid;
+ }
- QQmlPropertyData *result = r->d()->propertyCache()->property(n, nullptr, nullptr);
- return result ? Attr_Data : Attr_Invalid;
+ return QV4::Object::getOwnProperty(m, id, p);
}
void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 5a684bfb4d..12d7114d2f 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -109,7 +109,7 @@ public:
static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static bool put(Managed *m, StringOrSymbol *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
- static PropertyAttributes query(const Managed *, StringOrSymbol *name);
+ static PropertyAttributes getOwnProperty(Managed *m, Identifier id, Property *p);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_toString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);