diff options
Diffstat (limited to 'src/qml/jsruntime/qv4object.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 152 |
1 files changed, 86 insertions, 66 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 0c6cde84ad..79a63d1ee6 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -50,6 +50,7 @@ #include "qv4string_p.h" #include "qv4identifiertable_p.h" #include "qv4jscall_p.h" +#include "qv4symbol_p.h" #include <stdint.h> @@ -57,9 +58,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(Object); -void Object::setInternalClass(InternalClass *ic) +void Object::setInternalClass(Heap::InternalClass *ic) { - d()->internalClass = ic; + d()->internalClass.set(engine(), ic); if (ic->isUsedAsProto) ic->updateProtoUsage(d()); Q_ASSERT(ic && ic->vtable); @@ -89,7 +90,7 @@ void Object::setProperty(uint index, const Property *p) void Heap::Object::setUsedAsProto() { - internalClass = internalClass->asProtoClass(); + internalClass.set(internalClass->engine, internalClass->asProtoClass()); } bool Object::setPrototype(Object *proto) @@ -121,7 +122,7 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property bool Object::putValue(uint memberIndex, const Value &value) { - QV4::InternalClass *ic = internalClass(); + Heap::InternalClass *ic = internalClass(); if (ic->engine->hasException) return false; @@ -148,37 +149,34 @@ bool Object::putValue(uint memberIndex, const Value &value) return true; } -void Object::defineDefaultProperty(const QString &name, const Value &value) +void Object::defineDefaultProperty(const QString &name, const Value &value, PropertyAttributes attributes) { ExecutionEngine *e = engine(); Scope scope(e); ScopedString s(scope, e->newIdentifier(name)); - defineDefaultProperty(s, value); + defineDefaultProperty(s, value, attributes); } -void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount) +void Object::defineDefaultProperty(const QString &name, jsCallFunction code, + int argumentCount, PropertyAttributes attributes) { ExecutionEngine *e = engine(); Scope scope(e); ScopedString s(scope, e->newIdentifier(name)); - ExecutionContext *global = e->rootContext(); - ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, s, code)); - function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount)); - defineDefaultProperty(s, function); + ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(e, s, code, argumentCount)); + defineDefaultProperty(s, function, attributes); } -void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount) +void Object::defineDefaultProperty(StringOrSymbol *nameOrSymbol, jsCallFunction code, + int argumentCount, PropertyAttributes attributes) { ExecutionEngine *e = engine(); Scope scope(e); - ExecutionContext *global = e->rootContext(); - ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, name, code)); - function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount)); - defineDefaultProperty(name, function); + ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(e, nameOrSymbol, code, argumentCount)); + defineDefaultProperty(nameOrSymbol, function, attributes); } -void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int), - ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int)) +void Object::defineAccessorProperty(const QString &name, jsCallFunction getter, jsCallFunction setter) { ExecutionEngine *e = engine(); Scope scope(e); @@ -186,16 +184,27 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter) defineAccessorProperty(s, getter, setter); } -void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int), - ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int)) +void Object::defineAccessorProperty(StringOrSymbol *name, jsCallFunction getter, jsCallFunction setter) { ExecutionEngine *v4 = engine(); QV4::Scope scope(v4); ScopedProperty p(scope); - ExecutionContext *global = v4->rootContext(); - p->setGetter(ScopedFunctionObject(scope, (getter ? FunctionObject::createBuiltinFunction(global, name, getter) : nullptr))); - p->setSetter(ScopedFunctionObject(scope, (setter ? FunctionObject::createBuiltinFunction(global, name, setter) : nullptr))); - insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); + QString n = name->toQString(); + if (n.at(0) == QLatin1Char('@')) + n = QChar::fromLatin1('[') + n.midRef(1) + QChar::fromLatin1(']'); + if (getter) { + ScopedString getName(scope, v4->newString(QString::fromLatin1("get ") + n)); + p->setGetter(ScopedFunctionObject(scope, FunctionObject::createBuiltinFunction(v4, getName, getter, 0))); + } else { + p->setGetter(nullptr); + } + if (setter) { + ScopedString setName(scope, v4->newString(QString::fromLatin1("set ") + n)); + p->setSetter(ScopedFunctionObject(scope, FunctionObject::createBuiltinFunction(v4, setName, setter, 0))); + } else { + p->setSetter(nullptr); + } + insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable); } @@ -221,13 +230,23 @@ void Object::defineReadonlyConfigurableProperty(const QString &name, const Value defineReadonlyConfigurableProperty(s, value); } -void Object::defineReadonlyConfigurableProperty(String *name, const Value &value) +void Object::defineReadonlyConfigurableProperty(StringOrSymbol *name, const Value &value) { insertMember(name, value, Attr_ReadOnly_ButConfigurable); } +void Object::addSymbolSpecies() +{ + Scope scope(engine()); + ScopedProperty p(scope); + p->setGetter(scope.engine->getSymbolSpecies()); + p->setSetter(nullptr); + insertMember(scope.engine->symbol_species(), p, QV4::Attr_Accessor|QV4::Attr_NotWritable|QV4::Attr_NotEnumerable); +} + void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack) { + Base::markObjects(b, stack); Object *o = static_cast<Object *>(b); if (o->memberData) o->memberData->mark(stack); @@ -242,10 +261,11 @@ 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; - InternalClass::addMember(this, s, attributes, &idx); + s->makeIdentifier(); + Heap::InternalClass::addMember(this, s->identifier(), attributes, &idx); if (attributes.isAccessor()) { setProperty(idx + GetterOffset, p->value); @@ -256,14 +276,14 @@ void Object::insertMember(String *s, const Property *p, PropertyAttributes attri } // Section 8.12.1 -void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p) +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(); + Identifier id = name->identifier(); uint member = internalClass()->find(id); if (member < UINT_MAX) { @@ -300,12 +320,12 @@ void Object::getOwnProperty(uint index, PropertyAttributes *attrs, Property *p) } // Section 8.12.2 -MemberData::Index Object::getValueOrSetter(String *name, PropertyAttributes *attrs) +PropertyIndex Object::getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs) { Q_ASSERT(name->asArrayIndex() == UINT_MAX); name->makeIdentifier(); - Identifier *id = name->identifier(); + Identifier id = name->identifier(); Heap::Object *o = d(); while (o) { @@ -321,7 +341,7 @@ MemberData::Index Object::getValueOrSetter(String *name, PropertyAttributes *att return { nullptr, nullptr }; } -ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs) +PropertyIndex Object::getValueOrSetter(uint index, PropertyAttributes *attrs) { Heap::Object *o = d(); while (o) { @@ -329,7 +349,7 @@ ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs) uint idx = o->arrayData->mappedIndex(index); if (idx != UINT_MAX) { *attrs = o->arrayData->attributes(index); - return { o->arrayData , attrs->isAccessor() ? idx + SetterOffset : idx }; + return { o->arrayData , o->arrayData->values.values + (attrs->isAccessor() ? idx + SetterOffset : idx) }; } } if (o->vtable()->type == Type_StringObject) { @@ -346,7 +366,7 @@ ArrayData::Index Object::getValueOrSetter(uint index, PropertyAttributes *attrs) return { nullptr, 0 }; } -bool Object::hasProperty(String *name) const +bool Object::hasProperty(StringOrSymbol *name) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -378,14 +398,14 @@ bool Object::hasProperty(uint index) const return false; } -bool Object::hasOwnProperty(String *name) const +bool Object::hasOwnProperty(StringOrSymbol *name) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) return hasOwnProperty(idx); name->makeIdentifier(); - Identifier *id = name->identifier(); + Identifier id = name->identifier(); if (internalClass()->find(id) < UINT_MAX) return true; @@ -418,7 +438,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<const Object *>(m)->internalGet(name, hasProperty); } @@ -428,7 +448,7 @@ ReturnedValue Object::getIndexed(const Managed *m, uint index, bool *hasProperty return static_cast<const Object *>(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<Object *>(m)->internalPut(name, value); } @@ -438,14 +458,14 @@ bool Object::putIndexed(Managed *m, uint index, const Value &value) return static_cast<Object *>(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) return queryIndexed(m, idx); name->makeIdentifier(); - Identifier *id = name->identifier(); + Identifier id = name->identifier(); const Object *o = static_cast<const Object *>(m); idx = o->internalClass()->find(id); @@ -468,7 +488,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<Object *>(m)->internalDeleteProperty(name); } @@ -525,9 +545,10 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint * } while (it->memberIndex < o->internalClass()->size) { - Identifier *n = o->internalClass()->nameMap.at(it->memberIndex); - if (!n) { + Identifier n = o->internalClass()->nameMap.at(it->memberIndex); + if (!n.isValid() || !n.asHeapObject()->internalClass->vtable->isString) { // accessor properties have a dummy entry with n == 0 + // symbol entries are supposed to be skipped ++it->memberIndex; continue; } @@ -536,7 +557,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint * PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex]; ++it->memberIndex; if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { - name->setM(o->engine()->identifierTable->stringFromIdentifier(n)); + name->setM(n.asHeapObject()); *attrs = a; pd->value = *o->propertyData(idx); if (a.isAccessor()) @@ -549,14 +570,14 @@ 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) return getIndexed(idx, hasProperty); name->makeIdentifier(); - Identifier *id = name->identifier(); + Identifier id = name->identifier(); Heap::Object *o = d(); while (o) { @@ -612,7 +633,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) @@ -623,9 +644,9 @@ bool Object::internalPut(String *name, const Value &value) return putIndexed(idx, value); name->makeIdentifier(); - Identifier *id = name->identifier(); + Identifier id = name->identifier(); - MemberData::Index memberIndex{nullptr, nullptr}; + PropertyIndex memberIndex{nullptr, nullptr}; uint member = internalClass()->find(id); PropertyAttributes attrs; if (member < UINT_MAX) { @@ -641,7 +662,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) { @@ -701,7 +722,7 @@ bool Object::internalPutIndexed(uint index, const Value &value) PropertyAttributes attrs; - ArrayData::Index arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : ArrayData::Index{ nullptr, 0 }; + PropertyIndex arrayIndex = arrayData() ? arrayData()->getValueOrSetter(index, &attrs) : PropertyIndex{ nullptr, 0 }; if (arrayIndex.isNull() && isStringObject()) { if (index < static_cast<StringObject *>(this)->length()) @@ -759,7 +780,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; @@ -769,11 +790,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()) { - InternalClass::removeMember(this, name->identifier()); + Heap::InternalClass::removeMember(this, id); return true; } return false; @@ -796,7 +818,7 @@ bool Object::internalDeleteIndexedProperty(uint index) } // Section 8.12.9 -bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionEngine *engine, StringOrSymbol *name, const Property *p, PropertyAttributes attrs) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -807,8 +829,8 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const uint memberIndex; - if (isArrayObject() && name->equals(engine->id_length())) { - Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length())); + if (isArrayObject() && name->identifier() == engine->id_length()->identifier()) { + Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()->identifier())); ScopedProperty lp(scope); PropertyAttributes cattrs; getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs); @@ -829,7 +851,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const } if (attrs.hasWritable() && !attrs.isWritable()) { cattrs.setWritable(false); - InternalClass::changeMember(this, engine->id_length(), cattrs); + Heap::InternalClass::changeMember(this, engine->id_length()->identifier(), cattrs); } if (!succeeded) return false; @@ -898,7 +920,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope return __defineOwnProperty__(engine, index, nullptr, p, attrs); } -bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs) { // clause 5 if (attrs.isEmpty()) @@ -977,7 +999,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String * current->merge(cattrs, p, attrs); if (member) { - InternalClass::changeMember(this, member, cattrs); + Heap::InternalClass::changeMember(this, member->identifier(), cattrs); setProperty(index, current); } else { setArrayAttributes(index, cattrs); @@ -1030,11 +1052,11 @@ void Object::copyArrayData(Object *other) setArrayLengthUnchecked(other->getLength()); } -uint Object::getLength(const Managed *m) +qint64 Object::getLength(const Managed *m) { Scope scope(static_cast<const Object *>(m)->engine()); ScopedValue v(scope, static_cast<Object *>(const_cast<Managed *>(m))->get(scope.engine->id_length())); - return v->toUInt32(); + return v->toLength(); } // 'var' is 'V' in 15.3.5.3. @@ -1132,12 +1154,10 @@ void Heap::ArrayObject::init(const QStringList &list) a->setArrayLengthUnchecked(len); } -uint ArrayObject::getLength(const Managed *m) +qint64 ArrayObject::getLength(const Managed *m) { const ArrayObject *a = static_cast<const ArrayObject *>(m); - if (a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->isInteger()) - return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->integerValue(); - return Primitive::toUInt32(a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->doubleValue()); + return a->propertyData(Heap::ArrayObject::LengthPropertyIndex)->toLength(); } QStringList ArrayObject::toQStringList() const |
