From f6d5079a44ca0dcb02cdc9c7adf9d3ab71df232d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 9 Apr 2013 14:28:20 +0200 Subject: Move functionality from PropertyDescriptor to Property Change-Id: I37177b5287ec323f54826cce1cb307ee7f678930 Reviewed-by: Simon Hausmann --- src/v4/qv4argumentsobject.cpp | 6 +- src/v4/qv4global.h | 6 +- src/v4/qv4object.cpp | 96 +++++++++++++++--------------- src/v4/qv4objectiterator.cpp | 6 +- src/v4/qv4objectproto.cpp | 18 +++--- src/v4/qv4propertydescriptor.h | 129 +++++++++++++++++++---------------------- src/v4/qv4runtime.cpp | 2 +- 7 files changed, 128 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/v4/qv4argumentsobject.cpp b/src/v4/qv4argumentsobject.cpp index e2fb9d6b07..0378112356 100644 --- a/src/v4/qv4argumentsobject.cpp +++ b/src/v4/qv4argumentsobject.cpp @@ -96,7 +96,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const PropertyDescriptor map; bool isMapped = false; if (pd && index < (uint)mappedArguments.size()) - isMapped = pd->isAccessor() && pd->get == context->engine->argumentsAccessors.at(index).get; + isMapped = pd->attrs.isAccessor() && pd->get == context->engine->argumentsAccessors.at(index).get; if (isMapped) { map = *pd; @@ -111,12 +111,12 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const ctx->strictMode = strict; isNonStrictArgumentsObject = true; - if (isMapped && desc->isData()) { + if (isMapped && desc->attrs.isData()) { if (desc->attrs.type() != PropertyAttributes::Generic) { Value arg = desc->value; map.set->call(ctx, Value::fromObject(this), &arg, 1); } - if (desc->attrs.writable()) + if (desc->attrs.isWritable()) *pd = map; } diff --git a/src/v4/qv4global.h b/src/v4/qv4global.h index 3ffa29b396..0e0a4f0f26 100644 --- a/src/v4/qv4global.h +++ b/src/v4/qv4global.h @@ -136,9 +136,9 @@ struct PropertyAttributes void resolveConfigurable() { configurable_set = true; } void resolveEnumerable() { enumerable_set = true; } - bool writable() const { return m_writable; } - bool enumerable() const { return m_enumerable; } - bool configurable() const { return m_configurable; } + bool isWritable() const { return m_writable; } + bool isEnumerable() const { return m_enumerable; } + bool isConfigurable() const { return m_configurable; } void clearType() { m_type = Data; type_set = false; } void clearWritable() { m_writable = false; writable_set = false; } diff --git a/src/v4/qv4object.cpp b/src/v4/qv4object.cpp index aa4a596c75..68f7c9ac0e 100644 --- a/src/v4/qv4object.cpp +++ b/src/v4/qv4object.cpp @@ -110,7 +110,7 @@ void Object::put(ExecutionContext *ctx, const QString &name, const Value &value) Value Object::getValue(const Value &thisObject, ExecutionContext *ctx, const PropertyDescriptor *p) { assert(p->attrs.type() != PropertyAttributes::Generic); - if (p->isData()) + if (p->attrs.isData()) return p->value; if (!p->get) return Value::undefinedValue(); @@ -120,7 +120,7 @@ Value Object::getValue(const Value &thisObject, ExecutionContext *ctx, const Pro void Object::putValue(ExecutionContext *ctx, PropertyDescriptor *pd, const Value &value) { - if (pd->isAccessor()) { + if (pd->attrs.isAccessor()) { if (pd->set) { Value args[1]; args[0] = value; @@ -130,7 +130,7 @@ void Object::putValue(ExecutionContext *ctx, PropertyDescriptor *pd, const Value goto reject; } - if (!pd->isWritable()) + if (!pd->attrs.isWritable()) goto reject; pd->value = value; @@ -144,7 +144,7 @@ void Object::putValue(ExecutionContext *ctx, PropertyDescriptor *pd, const Value void Object::putValue(ExecutionContext *ctx, PropertyDescriptor *pd, const Value &thisObject, const Value &value) { - if (pd->isAccessor()) { + if (pd->attrs.isAccessor()) { if (pd->set) { Value args[1]; args[0] = value; @@ -154,7 +154,7 @@ void Object::putValue(ExecutionContext *ctx, PropertyDescriptor *pd, const Value goto reject; } - if (!pd->isWritable()) + if (!pd->attrs.isWritable()) goto reject; pd->value = value; @@ -231,10 +231,10 @@ void Object::markObjects(Managed *that) for (int i = 0; i < o->internalClass->size; ++i) { const PropertyDescriptor &pd = o->memberData[i]; - if (pd.isData()) { + if (pd.attrs.isData()) { if (Managed *m = pd.value.asManaged()) m->mark(); - } else if (pd.isAccessor()) { + } else if (pd.attrs.isAccessor()) { if (pd.get) pd.get->mark(); if (pd.set) @@ -346,7 +346,7 @@ PropertyAttributes Object::query(Managed *m, ExecutionContext *ctx, String *name PropertyDescriptor *pd = that->__getPropertyDescriptor__(ctx, name); if (!pd || pd->attrs.type() == PropertyAttributes::Generic) return Attr_Invalid; - return pd->toPropertyAttributes(); + return pd->attrs; } PropertyAttributes Object::queryIndexed(Managed *m, ExecutionContext *ctx, uint index) @@ -355,7 +355,7 @@ PropertyAttributes Object::queryIndexed(Managed *m, ExecutionContext *ctx, uint PropertyDescriptor *pd = that->__getPropertyDescriptor__(ctx, index); if (!pd || pd->attrs.type() == PropertyAttributes::Generic) return Attr_Invalid; - return pd->toPropertyAttributes(); + return pd->attrs; } bool Object::deleteProperty(Managed *m, ExecutionContext *ctx, String *name) @@ -447,11 +447,11 @@ void Object::internalPut(ExecutionContext *ctx, String *name, const Value &value // clause 1 if (pd) { - if (pd->isAccessor()) { + if (pd->attrs.isAccessor()) { if (pd->set) goto cont; goto reject; - } else if (!pd->isWritable()) + } else if (!pd->attrs.isWritable()) goto reject; else if (isArrayObject() && name->isEqualTo(ctx->engine->id_length)) { bool ok; @@ -470,14 +470,14 @@ void Object::internalPut(ExecutionContext *ctx, String *name, const Value &value goto reject; } else { if (PropertyDescriptor *p = prototype->__getPropertyDescriptor__(ctx, name)) { - if (p->isAccessor()) { + if (p->attrs.isAccessor()) { if (p->set) goto cont; goto reject; } if (!extensible) goto reject; - if (!p->isWritable()) + if (!p->attrs.isWritable()) goto reject; } else { if (!extensible) @@ -493,7 +493,7 @@ void Object::internalPut(ExecutionContext *ctx, String *name, const Value &value pd = prototype->__getPropertyDescriptor__(ctx, name); // Clause 5 - if (pd && pd->isAccessor()) { + if (pd && pd->attrs.isAccessor()) { assert(pd->set != 0); Value args[1]; @@ -524,11 +524,11 @@ void Object::internalPutIndexed(ExecutionContext *ctx, uint index, const Value & // clause 1 if (pd) { - if (pd->isAccessor()) { + if (pd->attrs.isAccessor()) { if (pd->set) goto cont; goto reject; - } else if (!pd->isWritable()) + } else if (!pd->attrs.isWritable()) goto reject; else pd->value = value; @@ -538,14 +538,14 @@ void Object::internalPutIndexed(ExecutionContext *ctx, uint index, const Value & goto reject; } else { if (PropertyDescriptor *p = prototype->__getPropertyDescriptor__(ctx, index)) { - if (p->isAccessor()) { + if (p->attrs.isAccessor()) { if (p->set) goto cont; goto reject; } if (!extensible) goto reject; - if (!p->isWritable()) + if (!p->attrs.isWritable()) goto reject; } else { if (!extensible) @@ -560,7 +560,7 @@ void Object::internalPutIndexed(ExecutionContext *ctx, uint index, const Value & pd = prototype->__getPropertyDescriptor__(ctx, index); // Clause 5 - if (pd && pd->isAccessor()) { + if (pd && pd->attrs.isAccessor()) { assert(pd->set != 0); Value args[1]; @@ -589,7 +589,7 @@ bool Object::internalDeleteProperty(ExecutionContext *ctx, String *name) uint memberIdx = internalClass->find(name); if (memberIdx != UINT_MAX) { PropertyDescriptor &pd = memberData[memberIdx]; - if (pd.isConfigurable()) { + if (pd.attrs.isConfigurable()) { internalClass->removeMember(this, name->identifier); memmove(memberData + memberIdx, memberData + memberIdx + 1, (internalClass->size - memberIdx)*sizeof(PropertyDescriptor)); return true; @@ -617,7 +617,7 @@ bool Object::internalDeleteIndexedProperty(ExecutionContext *ctx, uint index) if (!pd || pd->attrs.type() == PropertyAttributes::Generic) return true; - if (pd->isConfigurable()) { + if (pd->attrs.isConfigurable()) { pd->attrs.clear(); pd->value = Value::undefinedValue(); if (sparseArray) { @@ -646,9 +646,9 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr if (isArrayObject() && name->isEqualTo(ctx->engine->id_length)) { PropertyDescriptor *lp = memberData + ArrayObject::LengthPropertyIndex; assert(0 == internalClass->find(ctx->engine->id_length)); - if (desc->isEmpty() || desc->isSubset(lp)) + if (desc->attrs.isEmpty() || desc->isSubset(desc->attrs, lp)) return true; - if (!lp->isWritable() || desc->attrs.type() == PropertyAttributes::Accessor || desc->isConfigurable() || desc->isEnumerable()) + if (!lp->attrs.isWritable() || desc->attrs.type() == PropertyAttributes::Accessor || desc->attrs.isConfigurable() || desc->attrs.isEnumerable()) goto reject; bool succeeded = true; if (desc->attrs.type() == PropertyAttributes::Data) { @@ -659,7 +659,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr succeeded = setArrayLength(l); } if (desc->attrs.hasWritable()) - lp->attrs.setWritable(desc->attrs.writable()); + lp->attrs.setWritable(desc->attrs.isWritable()); if (!succeeded) goto reject; return true; @@ -676,9 +676,9 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr if (!extensible) goto reject; // clause 4 - PropertyDescriptor *pd = insertMember(name, desc->toPropertyAttributes()); + PropertyDescriptor *pd = insertMember(name, desc->attrs); *pd = *desc; - pd->fullyPopulated(); + pd->fullyPopulated(&pd->attrs); return true; } @@ -694,7 +694,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop PropertyDescriptor *current; // 15.4.5.1, 4b - if (isArrayObject() && index >= arrayLength() && !memberData[ArrayObject::LengthPropertyIndex].isWritable()) + if (isArrayObject() && index >= arrayLength() && !memberData[ArrayObject::LengthPropertyIndex].attrs.isWritable()) goto reject; if (isNonStrictArgumentsObject) @@ -714,7 +714,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop // clause 4 PropertyDescriptor *pd = arrayInsert(index); *pd = *desc; - pd->fullyPopulated(); + pd->fullyPopulated(&pd->attrs); return true; } @@ -728,31 +728,31 @@ reject: bool Object::__defineOwnProperty__(ExecutionContext *ctx, PropertyDescriptor *current, const PropertyDescriptor *desc) { // clause 5 - if (desc->isEmpty()) + if (desc->attrs.isEmpty()) return true; // clause 6 - if (desc->isSubset(current)) + if (desc->isSubset(desc->attrs, current)) return true; // clause 7 - if (!current->isConfigurable()) { - if (desc->isConfigurable()) + if (!current->attrs.isConfigurable()) { + if (desc->attrs.isConfigurable()) goto reject; - if (desc->attrs.hasEnumerable() && desc->attrs.enumerable() != current->attrs.enumerable()) + if (desc->attrs.hasEnumerable() && desc->attrs.isEnumerable() != current->attrs.isEnumerable()) goto reject; } // clause 8 - if (desc->isGeneric()) + if (desc->attrs.isGeneric()) goto accept; // clause 9 - if (current->isData() != desc->isData()) { + if (current->attrs.isData() != desc->attrs.isData()) { // 9a - if (!current->isConfigurable()) + if (!current->attrs.isConfigurable()) goto reject; - if (current->isData()) { + if (current->attrs.isData()) { // 9b current->attrs.setType(PropertyAttributes::Accessor); current->attrs.clearWritable(); @@ -764,14 +764,14 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, PropertyDescriptor *cu current->attrs.setWritable(false); current->value = Value::undefinedValue(); } - } else if (current->isData() && desc->isData()) { // clause 10 - if (!current->isConfigurable() && !current->isWritable()) { - if (desc->isWritable() || !current->value.sameValue(desc->value)) + } else if (current->attrs.isData() && desc->attrs.isData()) { // clause 10 + if (!current->attrs.isConfigurable() && !current->attrs.isWritable()) { + if (desc->attrs.isWritable() || !current->value.sameValue(desc->value)) goto reject; } } else { // clause 10 - assert(current->isAccessor() && desc->isAccessor()); - if (!current->isConfigurable()) { + assert(current->attrs.isAccessor() && desc->attrs.isAccessor()); + if (!current->attrs.isConfigurable()) { if (desc->get && !(current->get == desc->get || (!current->get && (quintptr)desc->get == 0x1))) goto reject; if (desc->set && !(current->set == desc->set || (!current->set && (quintptr)desc->set == 0x1))) @@ -781,7 +781,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, PropertyDescriptor *cu accept: - *current += *desc; + current->merge(current->attrs, *desc); return true; reject: if (ctx->strictMode) @@ -973,7 +973,7 @@ void Object::arrayReserve(uint n) bool Object::setArrayLength(uint newLen) { assert(isArrayObject()); const PropertyDescriptor *lengthProperty = memberData + ArrayObject::LengthPropertyIndex; - if (lengthProperty && !lengthProperty->isWritable()) + if (lengthProperty && !lengthProperty->attrs.isWritable()) return false; uint oldLen = arrayLength(); bool ok = true; @@ -984,7 +984,7 @@ bool Object::setArrayLength(uint newLen) { SparseArrayNode *it = sparseArray->end()->previousNode(); while (1) { PropertyDescriptor &pd = arrayData[it->value]; - if (pd.attrs.type() != PropertyAttributes::Generic && !pd.isConfigurable()) { + if (pd.attrs.type() != PropertyAttributes::Generic && !pd.attrs.isConfigurable()) { ok = false; newLen = it->key() + 1; break; @@ -1005,7 +1005,7 @@ bool Object::setArrayLength(uint newLen) { PropertyDescriptor *it = arrayData + arrayDataLen; const PropertyDescriptor *begin = arrayData + newLen; while (--it >= begin) { - if (it->attrs.type() != PropertyAttributes::Generic && !it->isConfigurable()) { + if (it->attrs.type() != PropertyAttributes::Generic && !it->attrs.isConfigurable()) { ok = false; newLen = it - arrayData + 1; break; @@ -1025,10 +1025,10 @@ void Object::markArrayObjects() const { for (uint i = 0; i < arrayDataLen; ++i) { const PropertyDescriptor &pd = arrayData[i]; - if (pd.isData()) { + if (pd.attrs.isData()) { if (Managed *m = pd.value.asManaged()) m->mark(); - } else if (pd.isAccessor()) { + } else if (pd.attrs.isAccessor()) { if (pd.get) pd.get->mark(); if (pd.set) diff --git a/src/v4/qv4objectiterator.cpp b/src/v4/qv4objectiterator.cpp index a0cd1a69ca..29b0c96482 100644 --- a/src/v4/qv4objectiterator.cpp +++ b/src/v4/qv4objectiterator.cpp @@ -96,7 +96,7 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index) int k = arrayNode->key(); p = current->arrayAt(k); arrayNode = arrayNode->nextNode(); - if (p && (!(flags & EnumberableOnly) || p->isEnumerable())) { + if (p && (!(flags & EnumberableOnly) || p->attrs.isEnumerable())) { arrayIndex = k + 1; *index = k; return p; @@ -109,7 +109,7 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index) while (arrayIndex < current->arrayDataLen) { p = current->arrayAt(arrayIndex); ++arrayIndex; - if (p && p->attrs.type() != PropertyAttributes::Generic && (!(flags & EnumberableOnly) || p->isEnumerable())) { + if (p && p->attrs.type() != PropertyAttributes::Generic && (!(flags & EnumberableOnly) || p->attrs.isEnumerable())) { *index = arrayIndex - 1; return p; } @@ -138,7 +138,7 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index) p = current->memberData + memberIndex; ++memberIndex; - if (!(flags & EnumberableOnly) || p->isEnumerable()) { + if (!(flags & EnumberableOnly) || p->attrs.isEnumerable()) { *name = n; return p; } diff --git a/src/v4/qv4objectproto.cpp b/src/v4/qv4objectproto.cpp index 3e02d2c586..0721aa1b4a 100644 --- a/src/v4/qv4objectproto.cpp +++ b/src/v4/qv4objectproto.cpp @@ -299,7 +299,7 @@ Value ObjectPrototype::method_isSealed(SimpleCallContext *ctx) PropertyDescriptor *pd = it.next(&name, &index); if (!pd) break; - if (pd->attrs.configurable()) + if (pd->attrs.isConfigurable()) return Value::fromBoolean(false); } return Value::fromBoolean(true); @@ -321,7 +321,7 @@ Value ObjectPrototype::method_isFrozen(SimpleCallContext *ctx) PropertyDescriptor *pd = it.next(&name, &index); if (!pd) break; - if (pd->isWritable() || pd->isConfigurable()) + if (pd->attrs.isWritable() || pd->attrs.isConfigurable()) return Value::fromBoolean(false); } return Value::fromBoolean(true); @@ -423,7 +423,7 @@ Value ObjectPrototype::method_propertyIsEnumerable(SimpleCallContext *ctx) Object *o = ctx->thisObject.toObject(ctx); PropertyDescriptor *pd = o->__getOwnProperty__(ctx, p); - return Value::fromBoolean(pd && pd->isEnumerable()); + return Value::fromBoolean(pd && pd->attrs.isEnumerable()); } Value ObjectPrototype::method_defineGetter(SimpleCallContext *ctx) @@ -508,7 +508,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope } if (o->__hasProperty__(ctx, ctx->engine->id_writable)) { - if (desc->isAccessor()) + if (desc->attrs.isAccessor()) ctx->throwTypeError(); desc->attrs.setWritable(o->get(ctx, ctx->engine->id_writable).toBoolean()); // writable forces it to be a data descriptor @@ -516,7 +516,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope } if (o->__hasProperty__(ctx, ctx->engine->id_value)) { - if (desc->isAccessor()) + if (desc->attrs.isAccessor()) ctx->throwTypeError(); desc->value = o->get(ctx, ctx->engine->id_value); desc->attrs.setType(PropertyAttributes::Data); @@ -537,10 +537,10 @@ Value ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const Prope PropertyDescriptor pd; pd.attrs = Attr_Data; - if (desc->isData()) { + if (desc->attrs.isData()) { pd.value = desc->value; o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("value")), &pd); - pd.value = Value::fromBoolean(desc->attrs.writable()); + pd.value = Value::fromBoolean(desc->attrs.isWritable()); o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("writable")), &pd); } else { pd.value = desc->get ? Value::fromObject(desc->get) : Value::undefinedValue(); @@ -548,9 +548,9 @@ Value ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const Prope pd.value = desc->set ? Value::fromObject(desc->set) : Value::undefinedValue(); o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("set")), &pd); } - pd.value = Value::fromBoolean(desc->attrs.enumerable()); + pd.value = Value::fromBoolean(desc->attrs.isEnumerable()); o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("enumerable")), &pd); - pd.value = Value::fromBoolean(desc->attrs.configurable()); + pd.value = Value::fromBoolean(desc->attrs.isConfigurable()); o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("configurable")), &pd); return Value::fromObject(o); diff --git a/src/v4/qv4propertydescriptor.h b/src/v4/qv4propertydescriptor.h index 252d486c1d..0d77067743 100644 --- a/src/v4/qv4propertydescriptor.h +++ b/src/v4/qv4propertydescriptor.h @@ -51,6 +51,7 @@ namespace QQmlJS { namespace VM { struct FunctionObject; +struct PropertyDescriptor; struct Property { union { @@ -60,6 +61,28 @@ struct Property { FunctionObject *set; }; }; + + // Section 8.10 + inline void fullyPopulated(PropertyAttributes *attrs) { + if (!attrs->hasType()) { + attrs->setType(PropertyAttributes::Data); + value = Value::undefinedValue(); + } + if (attrs->type() == PropertyAttributes::Data) { + attrs->resolveWritable(); + } else { + attrs->clearWritable(); + if ((quintptr)get == 0x1) + get = 0; + if ((quintptr)set == 0x1) + set = 0; + } + attrs->resolveEnumerable(); + attrs->resolveConfigurable(); + } + + inline bool isSubset(const PropertyAttributes &attrs, PropertyDescriptor *other) const; + inline void merge(PropertyAttributes &attrs, const PropertyDescriptor &other); }; struct PropertyDescriptor : public Property @@ -79,79 +102,49 @@ struct PropertyDescriptor : public Property pd.attrs.setType(PropertyAttributes::Accessor); return pd; } +}; - PropertyAttributes toPropertyAttributes() const { - return attrs; - } - - // Section 8.10 - inline void fullyPopulated() { - if (!attrs.hasType()) { - attrs.setType(PropertyAttributes::Data); - value = Value::undefinedValue(); - } - if (attrs.type() == PropertyAttributes::Data) { - attrs.resolveWritable(); - } else { - attrs.clearWritable(); - if ((quintptr)get == 0x1) - get = 0; - if ((quintptr)set == 0x1) - set = 0; - } - attrs.resolveEnumerable(); - attrs.resolveConfigurable(); - } - - inline bool isData() const { return attrs.isData(); } - inline bool isAccessor() const { return attrs.isAccessor(); } - inline bool isGeneric() const { return attrs.isGeneric(); } - - inline bool isWritable() const { return attrs.writable(); } - inline bool isEnumerable() const { return attrs.enumerable(); } - inline bool isConfigurable() const { return attrs.configurable(); } - - inline bool isEmpty() const { - return attrs.isEmpty(); - } - inline bool isSubset(PropertyDescriptor *other) const { - if (attrs.type() != PropertyAttributes::Generic && attrs.type() != other->attrs.type()) - return false; - if (attrs.hasEnumerable() && attrs.enumerable() != other->attrs.enumerable()) - return false; - if (attrs.hasConfigurable() && attrs.configurable() != other->attrs.configurable()) - return false; - if (attrs.hasWritable() && attrs.writable() != other->attrs.writable()) +inline bool Property::isSubset(const PropertyAttributes &attrs, PropertyDescriptor *other) const +{ + if (attrs.type() != PropertyAttributes::Generic && attrs.type() != other->attrs.type()) + return false; + if (attrs.hasEnumerable() && attrs.isEnumerable() != other->attrs.isEnumerable()) + return false; + if (attrs.hasConfigurable() && attrs.isConfigurable() != other->attrs.isConfigurable()) + return false; + if (attrs.hasWritable() && attrs.isWritable() != other->attrs.isWritable()) + return false; + if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other->value)) + return false; + if (attrs.type() == PropertyAttributes::Accessor) { + if (get != other->get) return false; - if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other->value)) + if (set != other->set) return false; - if (attrs.type() == PropertyAttributes::Accessor) { - if (get != other->get) - return false; - if (set != other->set) - return false; - } - return true; } - inline void operator+=(const PropertyDescriptor &other) { - if (other.attrs.hasEnumerable()) - attrs.setEnumerable(other.attrs.enumerable()); - if (other.attrs.hasConfigurable()) - attrs.setConfigurable(other.attrs.configurable()); - if (other.attrs.hasWritable()) - attrs.setWritable(other.attrs.writable()); - if (other.attrs.type() == PropertyAttributes::Accessor) { - attrs.setType(PropertyAttributes::Accessor); - if (other.get) - get = ((quintptr)other.get == 0x1) ? 0 : other.get; - if (other.set) - set = ((quintptr)other.set == 0x1) ? 0 : other.set; - } else if (other.attrs.type() == PropertyAttributes::Data){ - attrs.setType(PropertyAttributes::Data); - value = other.value; - } + return true; +} + +inline void Property::merge(PropertyAttributes &attrs, const PropertyDescriptor &other) +{ + if (other.attrs.hasEnumerable()) + attrs.setEnumerable(other.attrs.isEnumerable()); + if (other.attrs.hasConfigurable()) + attrs.setConfigurable(other.attrs.isConfigurable()); + if (other.attrs.hasWritable()) + attrs.setWritable(other.attrs.isWritable()); + if (other.attrs.type() == PropertyAttributes::Accessor) { + attrs.setType(PropertyAttributes::Accessor); + if (other.get) + get = ((quintptr)other.get == 0x1) ? 0 : other.get; + if (other.set) + set = ((quintptr)other.set == 0x1) ? 0 : other.set; + } else if (other.attrs.type() == PropertyAttributes::Data){ + attrs.setType(PropertyAttributes::Data); + value = other.value; } -}; +} + } // namespace VM } // namespace QQmlJS diff --git a/src/v4/qv4runtime.cpp b/src/v4/qv4runtime.cpp index 7fc078dd81..083bfea206 100644 --- a/src/v4/qv4runtime.cpp +++ b/src/v4/qv4runtime.cpp @@ -639,7 +639,7 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value uint idx = index.asArrayIndex(); if (idx < UINT_MAX) { PropertyDescriptor *p = o->nonSparseArrayAt(idx); - if (p && p->attrs.type() == PropertyAttributes::Data && p->isWritable()) { + if (p && p->attrs.type() == PropertyAttributes::Data && p->attrs.isWritable()) { p->value = value; return; } -- cgit v1.2.3