diff options
-rw-r--r-- | src/qml/jsruntime/jsruntime.pri | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 17 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4propertykey.cpp | 60 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4propertykey_p.h | 120 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4reflect.cpp | 17 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 31 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 29 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value.cpp | 17 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 2 |
10 files changed, 260 insertions, 36 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index 8b8732590f..243c912266 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -30,6 +30,7 @@ SOURCES += \ $$PWD/qv4numberobject.cpp \ $$PWD/qv4object.cpp \ $$PWD/qv4objectproto.cpp \ + $$PWD/qv4propertykey.cpp \ $$PWD/qv4proxy.cpp \ $$PWD/qv4qmlcontext.cpp \ $$PWD/qv4reflect.cpp \ @@ -91,6 +92,7 @@ HEADERS += \ $$PWD/qv4numberobject_p.h \ $$PWD/qv4object_p.h \ $$PWD/qv4objectproto_p.h \ + $$PWD/qv4propertykey_p.h \ $$PWD/qv4proxy_p.h \ $$PWD/qv4qmlcontext_p.h \ $$PWD/qv4reflect_p.h \ diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 607f8b4d28..e3b3423a9d 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -200,6 +200,7 @@ namespace Heap { struct CppStackFrame; class MemoryManager; class ExecutableAllocator; +struct PropertyKey; struct StringOrSymbol; struct String; struct Symbol; diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index daf31833d7..3287912c7d 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -48,6 +48,7 @@ #include "qv4string_p.h" #include "qv4jscall_p.h" #include "qv4symbol_p.h" +#include "qv4propertykey_p.h" #include <QtCore/QDateTime> #include <QtCore/QStringList> @@ -163,12 +164,12 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObj static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate(); ScopedValue v(scope, argc > 1 ? argv[1] : Primitive::undefinedValue()); - ScopedStringOrSymbol name(scope, v->toPropertyKey(scope.engine)); + ScopedPropertyKey name(scope, v->toPropertyKey(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); ScopedProperty desc(scope); - PropertyAttributes attrs = O->getOwnProperty(name->toPropertyKey(), desc); + PropertyAttributes attrs = O->getOwnProperty(name->toIdentifier(), desc); return fromPropertyDescriptor(scope.engine, desc, attrs); } @@ -284,7 +285,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(const FunctionObject *b, co return scope.engine->throwTypeError(); ScopedObject O(scope, argv[0]); - ScopedStringOrSymbol name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); + ScopedPropertyKey name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); @@ -295,7 +296,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(const FunctionObject *b, co if (scope.engine->hasException) return QV4::Encode::undefined(); - if (!O->defineOwnProperty(name->toPropertyKey(), pd, attrs)) + if (!O->defineOwnProperty(name->toIdentifier(), pd, attrs)) THROW_TYPE_ERROR(); return O.asReturnedValue(); @@ -577,13 +578,13 @@ ReturnedValue ObjectPrototype::method_valueOf(const FunctionObject *b, const Val ReturnedValue ObjectPrototype::method_hasOwnProperty(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { Scope scope(b); - ScopedStringOrSymbol P(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); + ScopedPropertyKey P(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); ScopedObject O(scope, thisObject->toObject(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); - bool r = O->getOwnProperty(P->toPropertyKey()) != Attr_Invalid; + bool r = O->getOwnProperty(P->toIdentifier()) != Attr_Invalid; return Encode(r); } @@ -609,14 +610,14 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(const FunctionObject *b, con ReturnedValue ObjectPrototype::method_propertyIsEnumerable(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { Scope scope(b); - ScopedStringOrSymbol p(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); + ScopedPropertyKey p(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); ScopedObject o(scope, thisObject->toObject(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); - PropertyAttributes attrs = o->getOwnProperty(p->toPropertyKey()); + PropertyAttributes attrs = o->getOwnProperty(p->toIdentifier()); return Encode(attrs.isEnumerable()); } diff --git a/src/qml/jsruntime/qv4propertykey.cpp b/src/qml/jsruntime/qv4propertykey.cpp new file mode 100644 index 0000000000..4678748ee8 --- /dev/null +++ b/src/qml/jsruntime/qv4propertykey.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4propertykey_p.h" + +#include <QtCore/qstring.h> +#include <qv4string_p.h> + +QV4::Heap::StringOrSymbol *QV4::PropertyKey::toStringOrSymbol(QV4::ExecutionEngine *e) +{ + if (isArrayIndex()) + return Primitive::fromUInt32(asArrayIndex()).toString(e); + return static_cast<Heap::StringOrSymbol *>(asStringOrSymbol()); +} + +QString QV4::PropertyKey::toQString() const +{ + if (isArrayIndex()) + return QString::number(asArrayIndex()); + Heap::Base *b = asStringOrSymbol(); + Q_ASSERT(b->internalClass->vtable->isStringOrSymbol); + Heap::StringOrSymbol *s = static_cast<Heap::StringOrSymbol *>(b); + return s->toQString(); +} diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h new file mode 100644 index 0000000000..2e33562514 --- /dev/null +++ b/src/qml/jsruntime/qv4propertykey_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QV4PROPERTYKEY_H +#define QV4PROPERTYKEY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qv4value_p.h> +#include <private/qv4identifier_p.h> + +QT_BEGIN_NAMESPACE + +class QString; + +namespace QV4 { + +struct PropertyKey : private Value +{ + // Property keys are Strings, Symbols or unsigned integers. + // For convenience we derive them from Values, allowing us to store them + // on the JS stack + // + // They do however behave somewhat different than a Value: + // * If the key is a String, the pointer to the string is stored in the identifier + // table and thus unique. + // * If the key is a Symbol it simply points to the referenced symbol object + // * if the key is an array index (a uint < UINT_MAX), it's encoded as an + // integer value + int id; + + static PropertyKey invalid() { PropertyKey key; key.setRawValue(0); return key; } + static PropertyKey fromArrayIndex(uint idx) { PropertyKey key; key.setInt_32(static_cast<int>(idx)); return key; } + bool isStringOrSymbol() const { return isManaged(); } + uint asArrayIndex() const { return isManaged() ? std::numeric_limits<uint>::max() : value(); } + uint isArrayIndex() const { return !isManaged(); } + static PropertyKey fromStringOrSymbol(Heap::StringOrSymbol *b) + { PropertyKey key; key.setM(reinterpret_cast<Heap::Base *>(b)); return key; } + Heap::StringOrSymbol *asStringOrSymbol() const { return reinterpret_cast<Heap::StringOrSymbol *>(heapObject()); } + + bool isString() const { + Heap::Base *s = heapObject(); + return s && s->internalClass->vtable->isString; + } + + bool isSymbol() const { + Heap::Base *s = heapObject(); + return s && s->internalClass->vtable->isString && s->internalClass->vtable->isStringOrSymbol; + } + + // ### temporary until we transitioned Identifier to PropertyKey + static PropertyKey fromIdentifier(Identifier id) { + if (id.isArrayIndex()) + return PropertyKey::fromArrayIndex(id.asArrayIndex()); + return PropertyKey::fromStringOrSymbol(id.asStringOrSymbol()); + } + + Identifier toIdentifier() const { + if (isArrayIndex()) + return Identifier::fromArrayIndex(asArrayIndex()); + return Identifier::fromStringOrSymbol(asStringOrSymbol()); + } + + Q_QML_EXPORT QString toQString() const; + Heap::StringOrSymbol *toStringOrSymbol(ExecutionEngine *e); + + bool operator ==(const PropertyKey &other) const { return id == other.id; } + bool operator !=(const PropertyKey &other) const { return id != other.id; } + bool operator <(const PropertyKey &other) const { return id < other.id; } +}; + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp index 7d8c8db089..41aa4b402e 100644 --- a/src/qml/jsruntime/qv4reflect.cpp +++ b/src/qml/jsruntime/qv4reflect.cpp @@ -41,6 +41,7 @@ #include "qv4symbol_p.h" #include "qv4runtimeapi_p.h" #include "qv4objectproto_p.h" +#include "qv4propertykey_p.h" using namespace QV4; @@ -120,7 +121,7 @@ ReturnedValue Reflect::method_defineProperty(const FunctionObject *f, const Valu return scope.engine->throwTypeError(); ScopedObject O(scope, argv[0]); - ScopedStringOrSymbol name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); + ScopedPropertyKey name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine)); if (scope.engine->hasException) return QV4::Encode::undefined(); @@ -131,7 +132,7 @@ ReturnedValue Reflect::method_defineProperty(const FunctionObject *f, const Valu if (scope.engine->hasException) return QV4::Encode::undefined(); - bool result = O->defineOwnProperty(name->toPropertyKey(), pd, attrs); + bool result = O->defineOwnProperty(name->toIdentifier(), pd, attrs); return Encode(result); } @@ -155,12 +156,12 @@ ReturnedValue Reflect::method_get(const FunctionObject *f, const Value *, const ScopedObject o(scope, static_cast<const Object *>(argv)); Value undef = Primitive::undefinedValue(); const Value *index = argc > 1 ? &argv[1] : &undef; - ScopedStringOrSymbol name(scope, index->toPropertyKey(scope.engine)); + ScopedPropertyKey name(scope, index->toPropertyKey(scope.engine)); if (scope.hasException()) return Encode::undefined(); ScopedValue receiver(scope, argc > 2 ? argv[2] : *o); - return Encode(o->get(name->toPropertyKey(), receiver)); + return Encode(o->get(name->toIdentifier(), receiver)); } ReturnedValue Reflect::method_getOwnPropertyDescriptor(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) @@ -198,10 +199,10 @@ ReturnedValue Reflect::method_has(const FunctionObject *f, const Value *, const return Encode(hasProperty); } - ScopedStringOrSymbol name(scope, index->toPropertyKey(scope.engine)); + ScopedPropertyKey name(scope, index->toPropertyKey(scope.engine)); if (scope.engine->hasException) return false; - (void) o->get(name, &hasProperty); + (void) o->get(name->toIdentifier(), nullptr, &hasProperty); return Encode(hasProperty); } @@ -245,10 +246,10 @@ ReturnedValue Reflect::method_set(const FunctionObject *f, const Value *, const const Value &val = argc > 2 ? argv[2] : undef; ScopedValue receiver(scope, argc >3 ? argv[3] : argv[0]); - Scoped<StringOrSymbol> propertyKey(scope, index->toPropertyKey(scope.engine)); + ScopedPropertyKey propertyKey(scope, index->toPropertyKey(scope.engine)); if (scope.engine->hasException) return false; - bool result = o->put(propertyKey->toPropertyKey(), val, receiver); + bool result = o->put(propertyKey->toIdentifier(), val, receiver); return Encode(result); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 87a1f665b5..eee94a2f60 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -333,11 +333,10 @@ bool Runtime::method_deleteProperty(ExecutionEngine *engine, const Value &base, if (n < UINT_MAX) return o->deleteProperty(Identifier::fromArrayIndex(n)); - Scoped<StringOrSymbol> key(scope, index.toPropertyKey(engine)); + ScopedPropertyKey key(scope, index.toPropertyKey(engine)); if (engine->hasException) return false; - Identifier id = key->toPropertyKey(); - return o->deleteProperty(id); + return o->deleteProperty(key->toIdentifier()); } bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex) @@ -372,10 +371,10 @@ QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left if (!ro) return engine->throwTypeError(); Scope scope(engine); - ScopedStringOrSymbol s(scope, left.toPropertyKey(engine)); + ScopedPropertyKey s(scope, left.toPropertyKey(engine)); if (scope.hasException()) return Encode::undefined(); - bool r = ro->hasProperty(s->toPropertyKey()); + bool r = ro->hasProperty(s->toIdentifier()); return Encode(r); } @@ -638,10 +637,10 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine, Q_ASSERT(!!o); // can't fail as null/undefined is covered above } - ScopedStringOrSymbol name(scope, index.toPropertyKey(engine)); + ScopedPropertyKey name(scope, index.toPropertyKey(engine)); if (scope.hasException()) return Encode::undefined(); - return o->get(name); + return o->get(name->toIdentifier()); } ReturnedValue Runtime::method_loadElement(ExecutionEngine *engine, const Value &object, const Value &index) @@ -684,10 +683,10 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val return o->put(idx, value); } - ScopedStringOrSymbol name(scope, index.toPropertyKey(engine)); + ScopedPropertyKey name(scope, index.toPropertyKey(engine)); if (engine->hasException) return false; - return o->put(name, value); + return o->put(name->toIdentifier(), value); } void Runtime::method_storeElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) @@ -1202,11 +1201,11 @@ ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, ScopedValue thisObject(scope, base->toObject(engine)); base = thisObject; - ScopedStringOrSymbol str(scope, index.toPropertyKey(engine)); + ScopedPropertyKey str(scope, index.toPropertyKey(engine)); if (engine->hasException) return Encode::undefined(); - ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str)); + ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str->toIdentifier())); if (!f) return engine->throwTypeError(); @@ -1452,7 +1451,7 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId if (!additionalArgs) return o->asReturnedValue(); - Scoped<StringOrSymbol> name(scope); + ScopedPropertyKey name(scope); ScopedProperty pd(scope); for (int i = 0; i < additionalArgs; ++i) { Q_ASSERT(args->isInteger()); @@ -1468,7 +1467,7 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, int classId pd->value = Primitive::emptyValue(); pd->set = args[2]; } - bool ok = o->defineOwnProperty(name->toPropertyKey(), pd, (arg == ObjectLiteralArgument::Value ? Attr_Data : Attr_Accessor)); + bool ok = o->defineOwnProperty(name->toIdentifier(), pd, (arg == ObjectLiteralArgument::Value ? Attr_Data : Attr_Accessor)); if (!ok) return engine->throwTypeError(); @@ -1523,7 +1522,7 @@ ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classInde ScopedObject receiver(scope, *constructor); - ScopedStringOrSymbol propertyName(scope); + ScopedPropertyKey propertyName(scope); ScopedFunctionObject function(scope); ScopedProperty property(scope); const CompiledData::Method *methods = cls->methodTable(); @@ -1536,9 +1535,9 @@ ReturnedValue Runtime::method_createClass(ExecutionEngine *engine, int classInde return Encode::undefined(); ++computedNames; } else { - propertyName = unit->runtimeStrings[methods[i].name]; + propertyName = PropertyKey::fromStringOrSymbol(unit->runtimeStrings[methods[i].name]); } - Identifier id = propertyName->toPropertyKey(); + Identifier id = propertyName->toIdentifier(); QV4::Function *f = unit->runtimeFunctions[methods[i].function]; Q_ASSERT(f); function = FunctionObject::createMemberFunction(current, f); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 73ee17cd40..1a5837935c 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -53,6 +53,7 @@ #include "qv4engine_p.h" #include "qv4value_p.h" #include "qv4property_p.h" +#include "qv4propertykey_p.h" #ifdef V4_USE_VALGRIND #include <valgrind/memcheck.h> @@ -240,6 +241,34 @@ struct ScopedValue Value *ptr; }; + +struct ScopedPropertyKey +{ + ScopedPropertyKey(const Scope &scope) + { + ptr = reinterpret_cast<PropertyKey *>(scope.alloc<Scope::Uninitialized>()); + *ptr = PropertyKey::invalid(); + } + + ScopedPropertyKey(const Scope &scope, const PropertyKey &v) + { + ptr = reinterpret_cast<PropertyKey *>(scope.alloc<Scope::Uninitialized>()); + *ptr = v; + } + + ScopedPropertyKey &operator=(const PropertyKey &other) { + *ptr = other; + return *this; + } + + PropertyKey *operator->() { + return ptr; + } + + PropertyKey *ptr; +}; + + template<typename T> struct Scoped { diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index 9febd41a00..6b22967bfa 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -39,6 +39,7 @@ #include <qv4engine_p.h> #include <qv4runtime_p.h> #include <qv4string_p.h> +#include <qv4propertykey_p.h> #ifndef V4_BOOTSTRAP #include <qv4symbol_p.h> #include <qv4object_p.h> @@ -229,15 +230,25 @@ QString Value::toQString() const } // switch } -Heap::StringOrSymbol *Value::toPropertyKey(ExecutionEngine *e) const +QV4::PropertyKey Value::toPropertyKey(ExecutionEngine *e) const { + if (isInteger() && int_32() >= 0) + return PropertyKey::fromArrayIndex(static_cast<uint>(int_32())); + if (isStringOrSymbol()) { + Scope scope(e); + ScopedStringOrSymbol s(scope, this); + s->makeIdentifier(); + return PropertyKey::fromIdentifier(s->identifier()); + } Scope scope(e); ScopedValue v(scope, RuntimeHelpers::toPrimitive(*this, STRING_HINT)); if (!v->isStringOrSymbol()) v = v->toString(e); if (e->hasException) - return nullptr; - return static_cast<Heap::StringOrSymbol *>(v->m()); + return PropertyKey::invalid(); + ScopedStringOrSymbol s(scope, v); + s->makeIdentifier(); + return PropertyKey::fromIdentifier(s->identifier()); } #endif // V4_BOOTSTRAP diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 16bbf241ff..ac0a52f7a8 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -415,7 +415,7 @@ public: return reinterpret_cast<Heap::String *>(m()); return toString(e, *this); } - Heap::StringOrSymbol *toPropertyKey(ExecutionEngine *e) const; + QV4::PropertyKey toPropertyKey(ExecutionEngine *e) const; static Heap::String *toString(ExecutionEngine *e, Value val); Heap::Object *toObject(ExecutionEngine *e) const { |