From d1af494793961a31747b689cf307b65d99367486 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 Apr 2018 13:28:59 +0200 Subject: Change Objects vtable methods to take a StringOrSymbol This is needed for symbol support. Change-Id: I83db21f232168710d18999fd97d912016e86d630 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4object.cpp | 25 +++++++++++----------- src/qml/jsruntime/qv4object_p.h | 38 ++++++++++++++++----------------- src/qml/jsruntime/qv4qmlcontext.cpp | 14 ++++++++++-- src/qml/jsruntime/qv4qmlcontext_p.h | 4 ++-- src/qml/jsruntime/qv4qobjectwrapper.cpp | 23 ++++++++++++++------ src/qml/jsruntime/qv4qobjectwrapper_p.h | 6 +++--- src/qml/jsruntime/qv4string_p.h | 29 ++++++++++++++++++------- src/qml/jsruntime/qv4value_p.h | 14 ++++++++++++ 8 files changed, 101 insertions(+), 52 deletions(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index fc8131d99c..59540611b1 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -246,7 +246,7 @@ void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack) } } -void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes) +void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes) { uint idx; s->makeIdentifier(); @@ -305,7 +305,7 @@ void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p) } // Section 8.12.2 -PropertyIndex Object::getValueOrSetter(String *name, PropertyAttributes *attrs) +PropertyIndex Object::getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs) { Q_ASSERT(name->asArrayIndex() == UINT_MAX); @@ -423,7 +423,7 @@ ReturnedValue Object::call(const FunctionObject *f, const Value *, const Value * return f->engine()->throwTypeError(); } -ReturnedValue Object::get(const Managed *m, String *name, bool *hasProperty) +ReturnedValue Object::get(const Managed *m, StringOrSymbol *name, bool *hasProperty) { return static_cast(m)->internalGet(name, hasProperty); } @@ -433,7 +433,7 @@ ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty return static_cast(m)->internalGetIndexed(index, hasProperty); } -bool Object::put(Managed *m, String *name, const Value &value) +bool Object::put(Managed *m, StringOrSymbol *name, const Value &value) { return static_cast(m)->internalPut(name, value); } @@ -443,7 +443,7 @@ bool Object::putIndexed(Managed *m, uint index, const Value &value) return static_cast(m)->internalPutIndexed(index, value); } -PropertyAttributes Object::query(const Managed *m, String *name) +PropertyAttributes Object::query(const Managed *m, StringOrSymbol *name) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -473,7 +473,7 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index) return Attr_Invalid; } -bool Object::deleteProperty(Managed *m, String *name) +bool Object::deleteProperty(Managed *m, StringOrSymbol *name) { return static_cast(m)->internalDeleteProperty(name); } @@ -554,7 +554,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint * } // Section 8.12.3 -ReturnedValue Object::internalGet(String *name, bool *hasProperty) const +ReturnedValue Object::internalGet(StringOrSymbol *name, bool *hasProperty) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -617,7 +617,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) const // Section 8.12.5 -bool Object::internalPut(String *name, const Value &value) +bool Object::internalPut(StringOrSymbol *name, const Value &value) { ExecutionEngine *engine = this->engine(); if (engine->hasException) @@ -646,7 +646,7 @@ bool Object::internalPut(String *name, const Value &value) return false; } else if (!attrs.isWritable()) return false; - else if (isArrayObject() && name->equals(engine->id_length())) { + else if (isArrayObject() && id == engine->id_length()->identifier()) { bool ok; uint l = value.asArrayLength(&ok); if (!ok) { @@ -764,7 +764,7 @@ bool Object::internalPutIndexed(uint index, const Value &value) } // Section 8.12.7 -bool Object::internalDeleteProperty(String *name) +bool Object::internalDeleteProperty(StringOrSymbol *name) { if (internalClass()->engine->hasException) return false; @@ -774,11 +774,12 @@ bool Object::internalDeleteProperty(String *name) return deleteIndexedProperty(idx); name->makeIdentifier(); + Identifier id = name->identifier(); - uint memberIdx = internalClass()->find(name->identifier()); + uint memberIdx = internalClass()->find(id); if (memberIdx != UINT_MAX) { if (internalClass()->propertyData[memberIdx].isConfigurable()) { - Heap::InternalClass::removeMember(this, name->identifier()); + Heap::InternalClass::removeMember(this, id); return true; } return false; diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 885ae020f2..5d46e0e74b 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -166,13 +166,13 @@ struct ObjectVTable VTable vTable; ReturnedValue (*call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); ReturnedValue (*callAsConstructor)(const FunctionObject *, const Value *argv, int argc); - ReturnedValue (*get)(const Managed *, String *name, bool *hasProperty); + ReturnedValue (*get)(const Managed *, StringOrSymbol *name, bool *hasProperty); ReturnedValue (*getIndexed)(const Managed *, uint index, bool *hasProperty); - bool (*put)(Managed *, String *name, const Value &value); + bool (*put)(Managed *, StringOrSymbol *name, const Value &value); bool (*putIndexed)(Managed *, uint index, const Value &value); - PropertyAttributes (*query)(const Managed *, String *name); + PropertyAttributes (*query)(const Managed *, StringOrSymbol *name); PropertyAttributes (*queryIndexed)(const Managed *, uint index); - bool (*deleteProperty)(Managed *m, String *name); + bool (*deleteProperty)(Managed *m, StringOrSymbol *name); bool (*deleteIndexedProperty)(Managed *m, uint index); qint64 (*getLength)(const Managed *m); void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); @@ -243,7 +243,7 @@ struct Q_QML_EXPORT Object: Managed { void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = nullptr); void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = nullptr); - PropertyIndex getValueOrSetter(String *name, PropertyAttributes *attrs); + PropertyIndex getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs); PropertyIndex getValueOrSetter(uint index, PropertyAttributes *attrs); bool hasProperty(String *name) const; @@ -289,13 +289,13 @@ struct Q_QML_EXPORT Object: Managed { void defineReadonlyConfigurableProperty(const QString &name, const Value &value); void defineReadonlyConfigurableProperty(String *name, const Value &value); - void insertMember(String *s, const Value &v, PropertyAttributes attributes = Attr_Data) { + void insertMember(StringOrSymbol *s, const Value &v, PropertyAttributes attributes = Attr_Data) { Scope scope(engine()); ScopedProperty p(scope); p->value = v; insertMember(s, p, attributes); } - void insertMember(String *s, const Property *p, PropertyAttributes attributes); + void insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes); bool isExtensible() const { return d()->internalClass->extensible; } @@ -364,13 +364,13 @@ public: return false; } - inline ReturnedValue get(String *name, bool *hasProperty = nullptr) const + inline ReturnedValue get(StringOrSymbol *name, bool *hasProperty = nullptr) const { return vtable()->get(this, name, hasProperty); } inline ReturnedValue getIndexed(uint idx, bool *hasProperty = nullptr) const { return vtable()->getIndexed(this, idx, hasProperty); } // use the set variants instead, to customize throw behavior - inline bool put(String *name, const Value &v) + inline bool put(StringOrSymbol *name, const Value &v) { return vtable()->put(this, name, v); } inline bool putIndexed(uint idx, const Value &v) { return vtable()->putIndexed(this, idx, v); } @@ -381,7 +381,7 @@ public: }; // ES6: 7.3.3 Set (O, P, V, Throw) - inline bool set(String *name, const Value &v, ThrowOnFailure shouldThrow) + inline bool set(StringOrSymbol *name, const Value &v, ThrowOnFailure shouldThrow) { bool ret = vtable()->put(this, name, v); // ES6: 7.3.3, 6: If success is false and Throw is true, throw a TypeError exception. @@ -396,11 +396,11 @@ public: return ret; } - PropertyAttributes query(String *name) const + PropertyAttributes query(StringOrSymbol *name) const { return vtable()->query(this, name); } PropertyAttributes queryIndexed(uint index) const { return vtable()->queryIndexed(this, index); } - bool deleteProperty(String *name) + bool deleteProperty(StringOrSymbol *name) { return vtable()->deleteProperty(this, name); } bool deleteIndexedProperty(uint index) { return vtable()->deleteIndexedProperty(this, index); } @@ -413,24 +413,24 @@ public: protected: static ReturnedValue callAsConstructor(const FunctionObject *f, const Value *argv, int argc); static ReturnedValue call(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); - static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); + static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty); static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty); - static bool put(Managed *m, String *name, const Value &value); + 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, String *name); + static PropertyAttributes query(const Managed *m, StringOrSymbol *name); static PropertyAttributes queryIndexed(const Managed *m, uint index); - static bool deleteProperty(Managed *m, String *name); + static bool deleteProperty(Managed *m, StringOrSymbol *name); static bool deleteIndexedProperty(Managed *m, uint index); 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); private: - ReturnedValue internalGet(String *name, bool *hasProperty) const; + ReturnedValue internalGet(StringOrSymbol *name, bool *hasProperty) const; ReturnedValue internalGetIndexed(uint index, bool *hasProperty) const; - bool internalPut(String *name, const Value &value); + bool internalPut(StringOrSymbol *name, const Value &value); bool internalPutIndexed(uint index, const Value &value); - bool internalDeleteProperty(String *name); + bool internalDeleteProperty(StringOrSymbol *name); bool internalDeleteIndexedProperty(uint index); friend struct ObjectIterator; diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 785c4bc717..8f87f24745 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -78,9 +78,14 @@ void Heap::QQmlContextWrapper::destroy() Object::destroy(); } -ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasProperty) +ReturnedValue QQmlContextWrapper::get(const Managed *m, StringOrSymbol *n, bool *hasProperty) { Q_ASSERT(m->as()); + + if (n->isSymbol()) + return Object::get(m, n, hasProperty); + String *name = static_cast(n); + const QQmlContextWrapper *resource = static_cast(m); QV4::ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); @@ -224,9 +229,14 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP return Encode::undefined(); } -bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value) +bool QQmlContextWrapper::put(Managed *m, StringOrSymbol *n, const Value &value) { Q_ASSERT(m->as()); + + if (n->isSymbol()) + return Object::put(m, n, value); + String *name = static_cast(n); + QQmlContextWrapper *resource = static_cast(m); ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h index 647bef7fc1..86c5b62da2 100644 --- a/src/qml/jsruntime/qv4qmlcontext_p.h +++ b/src/qml/jsruntime/qv4qmlcontext_p.h @@ -98,8 +98,8 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object void setReadOnly(bool b) { d()->readOnly = b; } - static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); - static bool put(Managed *m, String *name, const Value &value); + static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty); + static bool put(Managed *m, StringOrSymbol *name, const Value &value); }; struct Q_QML_EXPORT QmlContext : public ExecutionContext diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index c49abd6fef..f57a7861ed 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -693,15 +693,22 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) return (engine->memoryManager->allocate(object))->asReturnedValue(); } -QV4::ReturnedValue QObjectWrapper::get(const Managed *m, String *name, bool *hasProperty) +QV4::ReturnedValue QObjectWrapper::get(const Managed *m, StringOrSymbol *name, bool *hasProperty) { + if (name->isSymbol()) + return Object::get(m, name, hasProperty); + String *n = static_cast(name); const QObjectWrapper *that = static_cast(m); QQmlContextData *qmlContext = that->engine()->callingQmlContext(); - return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true); + return that->getQmlProperty(qmlContext, n, IgnoreRevision, hasProperty, /*includeImports*/ true); } -bool QObjectWrapper::put(Managed *m, String *name, const Value &value) +bool QObjectWrapper::put(Managed *m, StringOrSymbol *n, const Value &value) { + if (n->isSymbol()) + return Object::put(m, n, value); + String *name = static_cast(n); + QObjectWrapper *that = static_cast(m); ExecutionEngine *v4 = that->engine(); @@ -726,8 +733,12 @@ bool QObjectWrapper::put(Managed *m, String *name, const Value &value) return true; } -PropertyAttributes QObjectWrapper::query(const Managed *m, String *name) +PropertyAttributes QObjectWrapper::query(const Managed *m, StringOrSymbol *name) { + if (name->isSymbol()) + return QV4::Object::query(m, name); + String *n = static_cast(name); + const QObjectWrapper *that = static_cast(m); const QObject *thatObject = that->d()->object(); if (QQmlData::wasDeleted(thatObject)) @@ -736,8 +747,8 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, String *name) ExecutionEngine *engine = that->engine(); QQmlContextData *qmlContext = engine->callingQmlContext(); QQmlPropertyData local; - if (that->findProperty(engine, qmlContext, name, IgnoreRevision, &local) - || name->equals(engine->id_destroy()) || name->equals(engine->id_toString())) + 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); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 1455acc1b3..56e20adbfa 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -193,9 +193,9 @@ protected: static QQmlPropertyData *findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local); QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const; - static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); - static bool put(Managed *m, String *name, const Value &value); - static PropertyAttributes query(const Managed *, String *name); + 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 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_p.h b/src/qml/jsruntime/qv4string_p.h index 0a316d85b5..a1763522b5 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -160,6 +160,12 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : public Managed { enum { IsStringOrSymbol = true }; + + inline void makeIdentifier() const; + Identifier identifier() const { return d()->identifier; } + + uint asArrayIndex() const; + #endif }; @@ -204,12 +210,6 @@ struct Q_QML_PRIVATE_EXPORT String : public StringOrSymbol { } uint toUInt(bool *ok) const; - void makeIdentifier() const { - if (d()->identifier.isValid()) - return; - makeIdentifierImpl(); - } - // slow path Q_NEVER_INLINE void makeIdentifierImpl() const; @@ -227,8 +227,6 @@ struct Q_QML_PRIVATE_EXPORT String : public StringOrSymbol { bool startsWithUpper() const { return d()->startsWithUpper(); } - Identifier identifier() const { return d()->identifier; } - protected: static bool isEqualTo(Managed *that, Managed *o); static uint getLength(const Managed *m); @@ -297,6 +295,21 @@ struct ComplexString : String { } }; +inline +void StringOrSymbol::makeIdentifier() const { + if (d()->identifier.isValid()) + return; + Q_ASSERT(isString()); + static_cast(this)->makeIdentifierImpl(); +} + +inline +uint StringOrSymbol::asArrayIndex() const { + if (isString()) + return static_cast(this)->asArrayIndex(); + return UINT_MAX; +} + template<> inline const StringOrSymbol *Value::as() const { return isManaged() && m()->internalClass->vtable->isStringOrSymbol ? static_cast(this) : nullptr; diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 03c9eda0f2..85c345f645 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -332,6 +332,8 @@ public: Q_ASSERT(isDouble()); } inline bool isString() const; + inline bool isStringOrSymbol() const; + inline bool isSymbol() const; inline bool isObject() const; inline bool isFunctionObject() const; inline bool isInt32() { @@ -504,6 +506,18 @@ inline bool Value::isString() const Heap::Base *b = heapObject(); return b && b->internalClass->vtable->isString; } + +bool Value::isStringOrSymbol() const +{ + Heap::Base *b = heapObject(); + return b && b->internalClass->vtable->isStringOrSymbol; +} + +bool Value::isSymbol() const +{ + Heap::Base *b = heapObject(); + return b && b->internalClass->vtable->isStringOrSymbol && !b->internalClass->vtable->isString; +} inline bool Value::isObject() const { Heap::Base *b = heapObject(); -- cgit v1.2.3