aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4object.cpp')
-rw-r--r--src/qml/jsruntime/qv4object.cpp152
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