diff options
author | Lars Knoll <[email protected]> | 2018-06-17 22:06:45 +0200 |
---|---|---|
committer | Lars Knoll <[email protected]> | 2018-06-25 07:36:22 +0000 |
commit | 3e1bb90da4c44455c8c307e01876cc2127bdb15c (patch) | |
tree | 6b9278e2612fe71ce84273857babf8494b8d91bc /src/qml | |
parent | f5a7953df3cb61edc6cc30175ea4f7f1c97deae6 (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 <[email protected]>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsapi/qjsvalue.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4identifier.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4identifier_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 146 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectiterator.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 13 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4proxy.cpp | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 38 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 19 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper_p.h | 2 |
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); |