From 74c658bb631fd5bab433b9867ff2e568a56ec082 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 15 Dec 2014 08:46:38 +0100 Subject: Make Property uses GC safe Change-Id: I5aa41a07a2d25e5c8a2d64bfa58a55fcd7aaf77e Reviewed-by: Simon Hausmann --- src/qml/jsapi/qjsvalueiterator.cpp | 2 +- src/qml/jsapi/qjsvalueiterator_p.h | 2 ++ src/qml/jsruntime/qv4argumentsobject.cpp | 12 ++++---- src/qml/jsruntime/qv4argumentsobject_p.h | 2 +- src/qml/jsruntime/qv4arraydata.cpp | 2 +- src/qml/jsruntime/qv4context.cpp | 2 +- src/qml/jsruntime/qv4functionobject.cpp | 10 +++--- src/qml/jsruntime/qv4object.cpp | 52 ++++++++++++++++---------------- src/qml/jsruntime/qv4object_p.h | 24 ++++++++------- src/qml/jsruntime/qv4objectiterator.cpp | 17 +++++------ src/qml/jsruntime/qv4objectproto.cpp | 45 +++++++++++++-------------- src/qml/jsruntime/qv4property_p.h | 30 +++++++++--------- src/qml/jsruntime/qv4scopedvalue_p.h | 5 ++- src/qml/jsruntime/qv4stringobject.cpp | 2 +- 14 files changed, 108 insertions(+), 99 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp index eed8cf50b2..002a84ee08 100644 --- a/src/qml/jsapi/qjsvalueiterator.cpp +++ b/src/qml/jsapi/qjsvalueiterator.cpp @@ -142,7 +142,7 @@ bool QJSValueIterator::next() return false; d_ptr->currentName = d_ptr->nextName; d_ptr->currentIndex = d_ptr->nextIndex; - d_ptr->currentProperty.copy(d_ptr->nextProperty, d_ptr->nextAttributes); + d_ptr->currentProperty.copy(&d_ptr->nextProperty, d_ptr->nextAttributes); d_ptr->currentAttributes = d_ptr->nextAttributes; QV4::ExecutionEngine *v4 = d_ptr->iterator.engine(); diff --git a/src/qml/jsapi/qjsvalueiterator_p.h b/src/qml/jsapi/qjsvalueiterator_p.h index fe1d3aa932..c8f149c75d 100644 --- a/src/qml/jsapi/qjsvalueiterator_p.h +++ b/src/qml/jsapi/qjsvalueiterator_p.h @@ -48,10 +48,12 @@ public: QJSValue value; QV4::PersistentValue iterator; + // ### GC QV4::Property currentProperty; QV4::PropertyAttributes currentAttributes; QV4::StringValue currentName; uint currentIndex; + // ### GC QV4::Property nextProperty; QV4::PropertyAttributes nextAttributes; QV4::StringValue nextName; diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index d9e6caf5ab..f0898088e2 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -88,7 +88,7 @@ void ArgumentsObject::fullyCreate() d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors); for (uint i = 0; i < (uint)numAccessors; ++i) { mappedArguments()->data[i] = context()->callData->args[i]; - arraySet(i, context()->engine->argumentsAccessors[i], Attr_Accessor); + arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor); } arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors); for (uint i = numAccessors; i < argCount; ++i) @@ -97,13 +97,13 @@ void ArgumentsObject::fullyCreate() d()->fullyCreated = true; } -bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, const Property &desc, PropertyAttributes attrs) +bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs) { fullyCreate(); Scope scope(engine); Property *pd = arrayData() ? arrayData()->getProperty(index) : 0; - Property map; + ScopedProperty map(scope); PropertyAttributes mapAttrs; bool isMapped = false; uint numAccessors = qMin((int)context()->function->formalParameterCount(), context()->realArgumentCount); @@ -114,7 +114,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con if (isMapped) { Q_ASSERT(arrayData()); mapAttrs = arrayData()->attributes(index); - map.copy(*pd, mapAttrs); + map->copy(pd, mapAttrs); setArrayAttributes(index, Attr_Data); pd = arrayData()->getProperty(index); pd->value = mappedArguments()->data[index]; @@ -127,10 +127,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con if (isMapped && attrs.isData()) { Q_ASSERT(arrayData()); - ScopedFunctionObject setter(scope, map.setter()); + ScopedFunctionObject setter(scope, map->setter()); ScopedCallData callData(scope, 1); callData->thisObject = this->asReturnedValue(); - callData->args[0] = desc.value; + callData->args[0] = desc->value; setter->call(callData); if (attrs.isWritable()) { diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index d54dfbf442..dfa7ec4219 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -112,7 +112,7 @@ struct ArgumentsObject: Object { !static_cast(m)->context()->strictMode; } - bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property &desc, PropertyAttributes attrs); + bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs); static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); static void putIndexed(Managed *m, uint index, const ValueRef value); static bool deleteIndexedProperty(Managed *m, uint index); diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 59ba6c4b03..f0277430ad 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -784,7 +784,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const ValueRef thisObject->initSparseArray(); while (n != sparse->sparse()->end()) { PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data; - thisObject->arraySet(n->value, *reinterpret_cast(sparse->arrayData() + n->value), a); + thisObject->arraySet(n->value, reinterpret_cast(sparse->arrayData() + n->value), a); n = n->nextNode(); } diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 001a586050..2857ff8568 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -121,7 +121,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) if (activation->hasProperty(name)) return; - Property desc(Primitive::undefinedValue()); + ScopedProperty desc(scope); PropertyAttributes attrs(Attr_Data); attrs.setConfigurable(deletable); activation->__defineOwnProperty__(scope.engine, name, desc, attrs); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 1d0e4a4f60..6fabedec95 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -464,7 +464,9 @@ Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, F f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount())); if (scope->d()->strictMode) { - Property pd(s.engine->thrower, s.engine->thrower); + ScopedProperty pd(s); + pd->value = s.engine->thrower; + pd->set = s.engine->thrower; f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } @@ -632,9 +634,9 @@ Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionOb len = 0; f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len)); - ExecutionEngine *v4 = s.engine; - - Property pd(v4->thrower, v4->thrower); + ScopedProperty pd(s); + pd->value = s.engine->thrower; + pd->set = s.engine->thrower; f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index cb2ff842d8..a333f84646 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -201,7 +201,7 @@ void Object::ensureMemberIndex(uint idx) d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx); } -void Object::insertMember(String *s, const Property &p, PropertyAttributes attributes) +void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes) { uint idx; InternalClass::addMember(this, s, attributes, &idx); @@ -212,10 +212,10 @@ void Object::insertMember(String *s, const Property &p, PropertyAttributes attri if (attributes.isAccessor()) { setHasAccessorProperty(); Property *pp = propertyAt(idx); - pp->value = p.value; - pp->set = p.set; + pp->value = p->value; + pp->set = p->set; } else { - d()->memberData->data[idx] = p.value; + d()->memberData->data[idx] = p->value; } } @@ -540,7 +540,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name it->arrayIndex = k + 1; *index = k; *attrs = a; - pd->copy(*p, a); + pd->copy(p, a); return; } } @@ -577,7 +577,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { *name = m->engine()->newString(n->string); *attrs = a; - pd->copy(*p, a); + pd->copy(p, a); return; } } @@ -846,7 +846,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, String *name, const Property *p, PropertyAttributes attrs) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -863,16 +863,16 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length)); Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex); cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex; - if (attrs.isEmpty() || p.isSubset(attrs, *lp, *cattrs)) + if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs)) return true; if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable()) goto reject; bool succeeded = true; if (attrs.type() == PropertyAttributes::Data) { bool ok; - uint l = p.value.asArrayLength(&ok); + uint l = p->value.asArrayLength(&ok); if (!ok) { - ScopedValue v(scope, p.value); + ScopedValue v(scope, p->value); engine->throwRangeError(v); return false; } @@ -897,9 +897,9 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const if (!isExtensible()) goto reject; // clause 4 - Property pd; - pd.copy(p, attrs); - pd.fullyPopulated(&attrs); + ScopedProperty pd(scope); + pd->copy(p, attrs); + pd->fullyPopulated(&attrs); insertMember(name, pd, attrs); return true; } @@ -911,7 +911,7 @@ reject: return false; } -bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs) { // 15.4.5.1, 4b if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable()) @@ -927,7 +927,7 @@ reject: return false; } -bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs) +bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs) { Property *current = 0; @@ -943,12 +943,12 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope if (!isExtensible()) goto reject; // clause 4 - Property pp; - pp.copy(p, attrs); - pp.fullyPopulated(&attrs); + Scope scope(engine); + ScopedProperty pp(scope); + pp->copy(p, attrs); + pp->fullyPopulated(&attrs); if (attrs == Attr_Data) { - Scope scope(engine); - ScopedValue v(scope, pp.value); + ScopedValue v(scope, pp->value); arraySet(index, v); } else { arraySet(index, pp, attrs); @@ -963,7 +963,7 @@ reject: return false; } -bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property &p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs) { // clause 5 if (attrs.isEmpty()) @@ -980,7 +980,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String * } // clause 6 - if (p.isSubset(attrs, *current, cattrs)) + if (p->isSubset(attrs, current, cattrs)) return true; // clause 7 @@ -1026,15 +1026,15 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String * } } else if (cattrs.isData() && attrs.isData()) { // clause 10 if (!cattrs.isConfigurable() && !cattrs.isWritable()) { - if (attrs.isWritable() || !current->value.sameValue(p.value)) + if (attrs.isWritable() || !current->value.sameValue(p->value)) goto reject; } } else { // clause 10 Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor()); if (!cattrs.isConfigurable()) { - if (!p.value.isEmpty() && current->value.val != p.value.val) + if (!p->value.isEmpty() && current->value.val != p->value.val) goto reject; - if (!p.set.isEmpty() && current->set.val != p.set.val) + if (!p->set.isEmpty() && current->set.val != p->set.val) goto reject; } } @@ -1057,7 +1057,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String * } -bool Object::__defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property &p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs) { Scope scope(engine); ScopedString s(scope, engine->newString(name)); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index d9c56b264d..084bd85fc5 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -93,11 +93,11 @@ struct Q_QML_EXPORT Object: Managed { bool hasOwnProperty(String *name) const; bool hasOwnProperty(uint index) const; - bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property &p, PropertyAttributes attrs); - bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property &p, PropertyAttributes attrs); - bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs); - bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property &p, PropertyAttributes attrs); - bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs); + bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs); // // helpers @@ -131,10 +131,12 @@ struct Q_QML_EXPORT Object: Managed { } void insertMember(String *s, const ValueRef v, PropertyAttributes attributes = Attr_Data) { - Property p(*v); + Scope scope(engine()); + ScopedProperty p(scope); + p->value = *v; insertMember(s, p, attributes); } - void insertMember(String *s, const Property &p, PropertyAttributes attributes); + void insertMember(String *s, const Property *p, PropertyAttributes attributes); inline ExecutionEngine *engine() const { return internalClass()->engine; } @@ -152,7 +154,7 @@ public: bool setArrayLength(uint newLen); void setArrayLengthUnchecked(uint l); - void arraySet(uint index, const Property &p, PropertyAttributes attributes = Attr_Data); + void arraySet(uint index, const Property *p, PropertyAttributes attributes = Attr_Data); void arraySet(uint index, ValueRef value); bool arrayPut(uint index, ValueRef value) { @@ -361,7 +363,7 @@ inline void Object::push_back(const ValueRef v) setArrayLengthUnchecked(idx + 1); } -inline void Object::arraySet(uint index, const Property &p, PropertyAttributes attributes) +inline void Object::arraySet(uint index, const Property *p, PropertyAttributes attributes) { // ### Clean up arrayCreate(); @@ -375,9 +377,9 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a } setArrayAttributes(index, attributes); Property *pd = ArrayData::insert(this, index, attributes.isAccessor()); - pd->value = p.value; + pd->value = p->value; if (attributes.isAccessor()) - pd->set = p.set; + pd->set = p->set; if (isArrayObject() && index >= getLength()) setArrayLengthUnchecked(index + 1); } diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index 5c8df40c4c..a5a15711f7 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -135,15 +135,15 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value) return Encode::null(); PropertyAttributes attrs; - Property p; uint index; Scope scope(object->engine()); + ScopedProperty p(scope); ScopedString name(scope); - next(name.getRef(), &index, &p, &attrs); + next(name.getRef(), &index, p, &attrs); if (attrs.isEmpty()) return Encode::null(); - value = object->objectValue()->getValue(&p, attrs); + value = object->objectValue()->getValue(p, attrs); if (!!name) return name->asReturnedValue(); @@ -157,15 +157,15 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value) return Encode::null(); PropertyAttributes attrs; - Property p; uint index; Scope scope(object->engine()); + ScopedProperty p(scope); ScopedString name(scope); - next(name.getRef(), &index, &p, &attrs); + next(name.getRef(), &index, p, &attrs); if (attrs.isEmpty()) return Encode::null(); - value = object->objectValue()->getValue(&p, attrs); + value = object->objectValue()->getValue(p, attrs); if (!!name) return name->asReturnedValue(); @@ -179,12 +179,11 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString() return Encode::null(); PropertyAttributes attrs; - // ### GC - Property p; uint index; Scope scope(object->engine()); + ScopedProperty p(scope); ScopedString name(scope); - next(name.getRef(), &index, &p, &attrs); + next(name.getRef(), &index, p, &attrs); if (attrs.isEmpty()) return Encode::null(); diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 0a592bb7d7..31e65d4e43 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -109,8 +109,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor) defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2); ScopedContext global(scope, scope.engine->rootContext()); - Property p(ScopedFunctionObject(scope, BuiltinFunction::create(global, v4->id___proto__, method_get_proto)), - ScopedFunctionObject(scope, BuiltinFunction::create(global, v4->id___proto__, method_set_proto))); + ScopedProperty p(scope); + p->value = BuiltinFunction::create(global, v4->id___proto__, method_get_proto); + p->set = BuiltinFunction::create(global, v4->id___proto__, method_set_proto); insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable); } @@ -185,9 +186,9 @@ ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx) return Encode::undefined(); ScopedValue attributes(scope, ctx->argument(2)); - Property pd; + ScopedProperty pd(scope); PropertyAttributes attrs; - toPropertyDescriptor(scope.engine, attributes, &pd, &attrs); + toPropertyDescriptor(scope.engine, attributes, pd, &attrs); if (scope.engine->hasException) return Encode::undefined(); @@ -211,17 +212,17 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx) ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly); ScopedString name(scope); + ScopedProperty pd(scope); + ScopedProperty n(scope); while (1) { uint index; PropertyAttributes attrs; - Property pd; - it.next(name.getRef(), &index, &pd, &attrs); + it.next(name.getRef(), &index, pd, &attrs); if (attrs.isEmpty()) break; - Property n; PropertyAttributes nattrs; - val = o->getValue(&pd, attrs); - toPropertyDescriptor(scope.engine, val, &n, &nattrs); + val = o->getValue(pd, attrs); + toPropertyDescriptor(scope.engine, val, n, &nattrs); if (scope.engine->hasException) return Encode::undefined(); bool ok; @@ -491,9 +492,9 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx) o = ctx->d()->engine->globalObject(); } - Property pd; - pd.value = f; - pd.set = Primitive::emptyValue(); + ScopedProperty pd(scope); + pd->value = f; + pd->set = Primitive::emptyValue(); o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor); return Encode::undefined(); } @@ -519,9 +520,9 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx) o = ctx->d()->engine->globalObject(); } - Property pd; - pd.value = Primitive::emptyValue(); - pd.set = f; + ScopedProperty pd(scope); + pd->value = Primitive::emptyValue(); + pd->set = f; o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor); return Encode::undefined(); } @@ -641,26 +642,26 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, c ScopedObject o(scope, engine->newObject()); ScopedString s(scope); - Property pd; + ScopedProperty pd(scope); if (attrs.isData()) { - pd.value = desc->value; + pd->value = desc->value; s = engine->newString(QStringLiteral("value")); o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data); - pd.value = Primitive::fromBoolean(attrs.isWritable()); + pd->value = Primitive::fromBoolean(attrs.isWritable()); s = engine->newString(QStringLiteral("writable")); o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data); } else { - pd.value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined(); + pd->value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined(); s = engine->newString(QStringLiteral("get")); o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data); - pd.value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined(); + pd->value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined(); s = engine->newString(QStringLiteral("set")); o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data); } - pd.value = Primitive::fromBoolean(attrs.isEnumerable()); + pd->value = Primitive::fromBoolean(attrs.isEnumerable()); s = engine->newString(QStringLiteral("enumerable")); o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data); - pd.value = Primitive::fromBoolean(attrs.isConfigurable()); + pd->value = Primitive::fromBoolean(attrs.isConfigurable()); s = engine->newString(QStringLiteral("configurable")); o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data); diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h index 50d3c0e351..ddee264b0e 100644 --- a/src/qml/jsruntime/qv4property_p.h +++ b/src/qml/jsruntime/qv4property_p.h @@ -68,18 +68,18 @@ struct Property { return pd; } - inline bool isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const; - inline void merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs); + inline bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const; + inline void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs); inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast(value.heapObject()) : 0; } inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast(set.heapObject()) : 0; } inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast(g)); } inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast(s)) : Value::fromHeapObject(0); } - void copy(const Property &other, PropertyAttributes attrs) { - value = other.value; + void copy(const Property *other, PropertyAttributes attrs) { + value = other->value; if (attrs.isAccessor()) - set = other.set; + set = other->set; } explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); } @@ -98,7 +98,7 @@ private: Property &operator=(const Property &); }; -inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const +inline bool Property::isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const { if (attrs.type() != PropertyAttributes::Generic && attrs.type() != otherAttrs.type()) return false; @@ -108,18 +108,18 @@ inline bool Property::isSubset(const PropertyAttributes &attrs, const Property & return false; if (attrs.hasWritable() && attrs.isWritable() != otherAttrs.isWritable()) return false; - if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other.value)) + if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other->value)) return false; if (attrs.type() == PropertyAttributes::Accessor) { - if (value.heapObject() != other.value.heapObject()) + if (value.heapObject() != other->value.heapObject()) return false; - if (set.heapObject() != other.set.heapObject()) + if (set.heapObject() != other->set.heapObject()) return false; } return true; } -inline void Property::merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) +inline void Property::merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) { if (otherAttrs.hasEnumerable()) attrs.setEnumerable(otherAttrs.isEnumerable()); @@ -129,13 +129,13 @@ inline void Property::merge(PropertyAttributes &attrs, const Property &other, Pr attrs.setWritable(otherAttrs.isWritable()); if (otherAttrs.type() == PropertyAttributes::Accessor) { attrs.setType(PropertyAttributes::Accessor); - if (!other.value.isEmpty()) - value = other.value; - if (!other.set.isEmpty()) - set = other.set; + if (!other->value.isEmpty()) + value = other->value; + if (!other->set.isEmpty()) + set = other->set; } else if (otherAttrs.type() == PropertyAttributes::Data){ attrs.setType(PropertyAttributes::Data); - value = other.value; + value = other->value; } } diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 1337da7f77..f408f8269d 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -501,10 +501,13 @@ struct ScopedProperty ScopedProperty(Scope &scope) { property = reinterpret_cast(scope.alloc(sizeof(Property) / sizeof(Value))); + property->value = Encode::undefined(); + property->set = Encode::undefined(); } Property *operator->() { return property; } - operator const Property &() { return *property; } + operator const Property *() const { return property; } + operator Property *() { return property; } Property *property; }; diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 3e30cbcae8..4dd4d5a8d4 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -135,7 +135,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String Property *pd = s->__getOwnProperty__(*index, &a); if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { *attrs = a; - p->copy(*pd, a); + p->copy(pd, a); return; } } -- cgit v1.2.3