Make Property uses GC safe
authorLars Knoll <lars.knoll@theqtcompany.com>
Mon, 15 Dec 2014 07:46:38 +0000 (08:46 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Sat, 20 Dec 2014 11:00:39 +0000 (12:00 +0100)
Change-Id: I5aa41a07a2d25e5c8a2d64bfa58a55fcd7aaf77e
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
14 files changed:
src/qml/jsapi/qjsvalueiterator.cpp
src/qml/jsapi/qjsvalueiterator_p.h
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4argumentsobject_p.h
src/qml/jsruntime/qv4arraydata.cpp
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4objectiterator.cpp
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4property_p.h
src/qml/jsruntime/qv4scopedvalue_p.h
src/qml/jsruntime/qv4stringobject.cpp

index eed8cf5..002a84e 100644 (file)
@@ -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();
index fe1d3aa..c8f149c 100644 (file)
@@ -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;
index d9e6caf..f089808 100644 (file)
@@ -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()) {
index d54dfbf..dfa7ec4 100644 (file)
@@ -112,7 +112,7 @@ struct ArgumentsObject: Object {
                 !static_cast<ArgumentsObject *>(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);
index 59ba6c4..f027743 100644 (file)
@@ -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<Property *>(sparse->arrayData() + n->value), a);
+                thisObject->arraySet(n->value, reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
 
                 n = n->nextNode();
             }
index 001a586..2857ff8 100644 (file)
@@ -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);
index 1d0e4a4..6fabede 100644 (file)
@@ -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);
 }
index cb2ff84..a333f84 100644 (file)
@@ -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));
index d9c56b2..084bd85 100644 (file)
@@ -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);
 }
index 5c8df40..a5a1571 100644 (file)
@@ -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();
 
index 0a592bb..31e65d4 100644 (file)
@@ -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);
 
index 50d3c0e..ddee264 100644 (file)
@@ -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<Heap::FunctionObject *>(value.heapObject()) : 0; }
     inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
     inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
     inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(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;
     }
 }
 
index 1337da7..f408f82 100644 (file)
@@ -501,10 +501,13 @@ struct ScopedProperty
     ScopedProperty(Scope &scope)
     {
         property = reinterpret_cast<Property*>(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;
 };
index 3e30cbc..4dd4d5a 100644 (file)
@@ -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;
             }
         }