Use SafeValue instead of Value in ScopedValue methods
authorLars Knoll <lars.knoll@digia.com>
Mon, 30 Sep 2013 20:41:12 +0000 (22:41 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 2 Oct 2013 14:07:33 +0000 (16:07 +0200)
Change-Id: Ie463efe600d498ce77d4b9e8b48abcfd61c1ab78
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
19 files changed:
src/imports/localstorage/plugin.cpp
src/qml/jsruntime/qv4arrayobject.cpp
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4jsonobject.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4regexpobject.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4scopedvalue_p.h
src/qml/jsruntime/qv4script.cpp
src/qml/jsruntime/qv4sequenceobject.cpp
src/qml/jsruntime/qv4serialize.cpp
src/qml/jsruntime/qv4value_def_p.h
src/qml/jsruntime/qv4value_p.h
src/qml/qml/qqmlvmemetaobject.cpp
src/qml/qml/qqmlxmlhttprequest.cpp
src/qml/types/qqmldelegatemodel.cpp
src/quick/items/context2d/qquickcontext2d.cpp

index ca69499..c4e3d51 100644 (file)
@@ -304,7 +304,7 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx)
             rows->sqlQuery = query;
 
             Scoped<Object> resultObject(scope, ctx->engine->newObject());
-            result = resultObject.asValue();
+            result = resultObject.asReturnedValue();
             // XXX optimize
             ScopedString s(scope);
             ScopedValue v(scope);
index 6f19597..92fa196 100644 (file)
@@ -523,7 +523,7 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx)
                     --instance->arrayAttributes;
                     *instance->arrayAttributes = Attr_Data;
                 }
-                instance->arrayData->value = v;
+                instance->arrayData->value = v.asReturnedValue();
             } else {
                 uint idx = instance->allocArrayValue(v);
                 instance->sparseArray->push_front(idx);
@@ -643,7 +643,7 @@ ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx)
         ctx->throwTypeError();
 
     ScopedCallData callData(scope, 3);
-    callData->args[2] = instance.asValue();
+    callData->args[2] = instance;
     callData->thisObject = ctx->argument(1);
     ScopedValue r(scope);
     ScopedValue v(scope);
index 11580b0..7ef0b96 100644 (file)
@@ -144,7 +144,7 @@ void FunctionObject::init(const StringRef n, bool createProto)
     if (createProto) {
         Scoped<Object> proto(s, scope->engine->newObject(scope->engine->protoClass));
         proto->memberData[Index_ProtoConstructor].value = this->asReturnedValue();
-        memberData[Index_Prototype].value = proto.asValue();
+        memberData[Index_Prototype].value = proto.asReturnedValue();
     }
 
     ScopedValue v(s, n.asReturnedValue());
@@ -443,7 +443,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
     ScopedObject obj(scope, v4->newObject(ic));
 
     ExecutionContext *context = v4->current;
-    callData->thisObject = obj.asValue();
+    callData->thisObject = obj.asReturnedValue();
     ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData);
 
     ScopedValue result(scope);
index 10d3075..2295fb5 100644 (file)
@@ -285,7 +285,7 @@ bool JsonParser::parseMember(ObjectRef o)
 
     ScopedString s(scope, context->engine->newIdentifier(key));
     Property *p = o->insertMember(s, Attr_Data);
-    p->value = val;
+    p->value = val.asReturnedValue();
 
     END;
     return true;
index aca41be..d189c19 100644 (file)
@@ -61,18 +61,6 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
 template <typename T1, typename T2>
 inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
 
-template <typename T>
-struct Returned : private T
-{
-    static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
-    T *getPointer() { return this; }
-    template<typename X>
-    static T *getPointer(Returned<X> *x) { return x->getPointer(); }
-    template<typename X>
-    Returned<X> *as() { return Returned<X>::create(Returned<X>::getPointer(this)); }
-    using T::asReturnedValue;
-};
-
 #define Q_MANAGED \
     public: \
         Q_MANAGED_CHECK \
index 4693834..21cbc8d 100644 (file)
@@ -185,7 +185,7 @@ ReturnedValue ObjectPrototype::method_create(SimpleCallContext *ctx)
     newObject->setPrototype(O->asObject());
 
     if (ctx->callData->argc > 1 && !ctx->callData->args[1].isUndefined()) {
-        ctx->callData->args[0] = newObject.asValue();
+        ctx->callData->args[0] = newObject.asReturnedValue();
         return method_defineProperties(ctx);
     }
 
index 90a1950..92cfdd8 100644 (file)
@@ -1640,7 +1640,7 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
     } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
         QVariant value = *qvariantPtr;
         QV4::ScopedValue rv(scope, engine->fromVariant(value));
-        if (QV4::QObjectWrapper *qobjectWrapper = rv->as<QV4::QObjectWrapper>()) {
+        if (QV4::Referenced<QObjectWrapper> qobjectWrapper = rv->asRef<QV4::QObjectWrapper>()) {
             if (QObject *object = qobjectWrapper->object())
                 QQmlData::get(object, true)->setImplicitDestructible();
         }
index 899938f..9c7fe94 100644 (file)
@@ -243,7 +243,8 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
 
     ScopedValue r(scope, callData->argument(0));
     ScopedValue f(scope, callData->argument(1));
-    if (RegExpObject *re = r->as<RegExpObject>()) {
+    Scoped<RegExpObject> re(scope, r);
+    if (re) {
         if (!f->isUndefined())
             ctx->throwTypeError();
 
@@ -273,11 +274,11 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
         }
     }
 
-    RegExp* re = RegExp::create(ctx->engine, pattern, ignoreCase, multiLine);
-    if (!re->isValid())
+    RegExp *regexp = RegExp::create(ctx->engine, pattern, ignoreCase, multiLine);
+    if (!regexp->isValid())
         ctx->throwSyntaxError(0);
 
-    return Encode(ctx->engine->newRegExpObject(re, global));
+    return Encode(ctx->engine->newRegExpObject(regexp, global));
 }
 
 ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
@@ -341,7 +342,7 @@ ReturnedValue RegExpPrototype::method_exec(SimpleCallContext *ctx)
     array->setArrayLengthUnchecked(len);
 
     array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result);
-    array->memberData[Index_ArrayInput].value = arg;
+    array->memberData[Index_ArrayInput].value = arg.asReturnedValue();
 
     if (r->global)
         r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]);
index b5c48af..95fe39b 100644 (file)
@@ -782,7 +782,7 @@ ReturnedValue __qmljs_call_property(ExecutionContext *context, const StringRef n
         }
 
         baseObject = __qmljs_convert_to_object(context, ValueRef(&callData->thisObject));
-        callData->thisObject = baseObject.asValue();
+        callData->thisObject = baseObject.asReturnedValue();
     }
 
     Scoped<FunctionObject> o(scope, baseObject->get(name));
index a1f6f4b..2e39f03 100644 (file)
@@ -169,18 +169,14 @@ struct ScopedValue
         return *this;
     }
 
-    Value *operator->() {
+    SafeValue *operator->() {
         return ptr;
     }
 
-    const Value *operator->() const {
+    const SafeValue *operator->() const {
         return ptr;
     }
 
-    operator const Value &() const {
-        return *ptr;
-    }
-
     ReturnedValue asReturnedValue() const { return ptr->val; }
 
     SafeValue *ptr;
@@ -326,12 +322,6 @@ struct Scoped
         return static_cast<T *>(ptr->managed());
     }
 
-    Value asValue() const {
-        if (ptr->m)
-            return *ptr;
-        return QV4::Primitive::undefinedValue();
-    }
-
     ReturnedValue asReturnedValue() const {
 #if QT_POINTER_SIZE == 8
         return ptr->val ? ptr->val : Primitive::undefinedValue().asReturnedValue();
@@ -427,7 +417,7 @@ struct ValueRef {
     operator Value *() {
         return ptr;
     }
-    Value *operator->() {
+    SafeValue *operator->() {
         return ptr;
     }
 
@@ -479,14 +469,14 @@ struct Referenced {
     }
 
     operator const T *() const {
-        return static_cast<T*>(ptr->managed());
+        return ptr ? static_cast<T*>(ptr->managed()) : 0;
     }
     const T *operator->() const {
         return static_cast<T*>(ptr->managed());
     }
 
     operator T *() {
-        return static_cast<T*>(ptr->managed());
+        return ptr ? static_cast<T*>(ptr->managed()) : 0;
     }
     T *operator->() {
         return static_cast<T*>(ptr->managed());
@@ -496,6 +486,19 @@ struct Referenced {
         return static_cast<T *>(ptr->managed());
     }
     ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); }
+    operator Returned<T> *() const { return ptr ? Returned<T>::create(getPointer()) : 0; }
+
+    bool operator==(const Referenced<T> &other) {
+        if (ptr == other.ptr)
+            return true;
+        return ptr && other.ptr && ptr->m == other.ptr->m;
+    }
+    bool operator!=(const Referenced<T> &other) {
+        if (ptr == other.ptr)
+            return false;
+        return !ptr || ptr->m != other.ptr->m;
+    }
+    bool operator!() const { return !ptr || !ptr->managed(); }
 
     static Referenced null() { return Referenced(Null); }
     bool isNull() const { return !ptr; }
@@ -642,6 +645,12 @@ inline Returned<T> *SafeValue::as()
     return Returned<T>::create(value_cast<T>(*this));
 }
 
+template<typename T> inline
+Referenced<T> SafeValue::asRef()
+{
+    return Referenced<T>(*this);
+}
+
 template<typename T>
 inline Safe<T> &Safe<T>::operator =(T *t)
 {
index 2350224..0dddbe8 100644 (file)
@@ -152,7 +152,7 @@ Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit
         vmFunction = compilationUnit->linkToEngine(v4);
         Q_ASSERT(vmFunction);
         Scope valueScope(v4);
-        ScopedValue holder(valueScope, Value::fromObject(new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)));
+        ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
         compilationUnitHolder = holder;
     } else
         vmFunction = 0;
index 10293a7..5c8f7db 100644 (file)
@@ -575,7 +575,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
 
 #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
     if (sequenceType == qMetaTypeId<SequenceType>()) { \
-        QV4::Scoped<QV4::Object> obj(scope, QV4::Value::fromObject(new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex))); \
+        QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex)); \
         return obj.asReturnedValue(); \
     } else
 
@@ -593,7 +593,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
 
 #define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
     if (sequenceType == qMetaTypeId<SequenceType>()) { \
-        QV4::Scoped<QV4::Object> obj(scope, QV4::Value::fromObject(new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >()))); \
+        QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >())); \
         return obj.asReturnedValue(); \
     } else
 
index f775a44..7d3214e 100644 (file)
@@ -392,7 +392,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
         array->arrayReserve(seqLength);
         for (quint32 ii = 0; ii < seqLength; ++ii) {
             value = deserialize(data, engine);
-            array->arrayData[ii].value = value;
+            array->arrayData[ii].value = value.asReturnedValue();
             array->arrayDataLen = ii + 1;
         }
         array->setArrayLengthUnchecked(seqLength);
index 11b70ef..f552798 100644 (file)
@@ -50,6 +50,18 @@ namespace QV4 {
 
 typedef uint Bool;
 
+template <typename T>
+struct Returned : private T
+{
+    static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
+    T *getPointer() { return this; }
+    template<typename X>
+    static T *getPointer(Returned<X> *x) { return x->getPointer(); }
+    template<typename X>
+    Returned<X> *as() { return Returned<X>::create(Returned<X>::getPointer(this)); }
+    using T::asReturnedValue;
+};
+
 struct Q_QML_EXPORT Value
 {
     /*
@@ -273,7 +285,6 @@ struct Q_QML_EXPORT Value
         return val;
     }
 
-    static Value fromObject(Object *o);
     static Value fromManaged(Managed *o);
 
     int toUInt16() const;
@@ -349,9 +360,10 @@ struct SafeValue : public Value
         val = v.val;
         return *this;
     }
-
     template<typename T>
-    Returned<T> *as();
+    inline Returned<T> *as();
+    template<typename T>
+    inline Referenced<T> asRef();
 };
 
 struct Q_QML_EXPORT Primitive : public Value
index e751a07..507c0f9 100644 (file)
@@ -165,18 +165,6 @@ inline Primitive Primitive::fromUInt32(uint i)
     return v;
 }
 
-inline Value Value::fromObject(Object *o)
-{
-    Value v;
-#if QT_POINTER_SIZE == 8
-    v.o = o;
-#else
-    v.tag = Managed_Type;
-    v.o = o;
-#endif
-    return v;
-}
-
 inline Value Value::fromManaged(Managed *m)
 {
     if (!m)
index dfba6bb..ecc6287 100644 (file)
@@ -1085,7 +1085,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
         // And, if the new value is a scarce resource, we need to ensure that it does not get
         // automatically released by the engine until no other references to it exist.
         QV4::ScopedValue newv(scope, QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value));
-        if (QV4::VariantObject *v = newv->as<QV4::VariantObject>())
+        if (QV4::Referenced<QV4::VariantObject> v = newv->asRef<QV4::VariantObject>())
             v->addVmePropertyReference();
 
         // Write the value and emit change signal as appropriate.
index 066a266..3097031 100644 (file)
@@ -1560,7 +1560,7 @@ void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me)
         QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
         if (callingContext) {
             QV4::ScopedCallData callData(scope, 0);
-            callData->thisObject = activationObject.asValue();
+            callData->thisObject = activationObject.asReturnedValue();
             callback->call(callData);
         }
 
index b87ed63..bfce21f 100644 (file)
@@ -3226,7 +3226,7 @@ public:
         if (!array)
             m->engine()->current->throwTypeError();
 
-        if (name == m->engine()->id_length) {
+        if (name->isEqualTo(m->engine()->id_length)) {
             if (hasProperty)
                 *hasProperty = true;
             return QV4::Encode(array->count());
index bab9a2c..6f7cd77 100644 (file)
@@ -929,7 +929,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV8Engine* engi
     }
 
     QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, new (v4->memoryManager) QQuickJSContext2DImageData(v4));
-    imageData->pixelData = pixelData.asValue();
+    imageData->pixelData = pixelData.asReturnedValue();
     return imageData.asReturnedValue();
 }
 
@@ -1386,7 +1386,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContex
            r->context->buffer()->setFillStyle(color);
            r->context->m_fillStyle = value;
        } else {
-           QQuickContext2DStyle *style = value->as<QQuickContext2DStyle>();
+           QV4::Scoped<QQuickContext2DStyle> style(scope, value->as<QQuickContext2DStyle>());
            if (style && style->brush != r->context->state.fillStyle) {
                r->context->state.fillStyle = style->brush;
                r->context->buffer()->setFillStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
@@ -1501,7 +1501,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallCont
             r->context->buffer()->setStrokeStyle(color);
             r->context->m_strokeStyle = value;
         } else {
-            QQuickContext2DStyle *style = value->as<QQuickContext2DStyle>();
+            QV4::Scoped<QQuickContext2DStyle> style(scope, value->as<QQuickContext2DStyle>());
             if (style && style->brush != r->context->state.strokeStyle) {
                 r->context->state.strokeStyle = style->brush;
                 r->context->buffer()->setStrokeStyle(style->brush, style->patternRepeatX, style->patternRepeatY);
@@ -2099,7 +2099,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ct
 
     QV4::ScopedValue value(scope, ctx->argument(0));
     r->context->beginPath();
-    if (QV4::QObjectWrapper *qobjectWrapper =value->as<QV4::QObjectWrapper>()) {
+    if (QV4::Referenced<QV4::QObjectWrapper> qobjectWrapper = value->asRef<QV4::QObjectWrapper>()) {
         if (QQuickPath *path = qobject_cast<QQuickPath*>(qobjectWrapper->object()))
             r->context->m_path = path->path();
     } else {
@@ -2964,7 +2964,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC
 
         pixmap = r->context->createPixmap(url);
     } else if (arg->isObject()) {
-        if (QV4::QObjectWrapper *qobjectWrapper = arg->as<QV4::QObjectWrapper>()) {
+        if (QV4::Referenced<QV4::QObjectWrapper> qobjectWrapper = arg->asRef<QV4::QObjectWrapper>()) {
             if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
                 pixmap.take(r->context->createPixmap(imageItem->source()));
             } else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
@@ -2974,7 +2974,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC
             } else {
                 V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
             }
-        } else if (QQuickJSContext2DImageData *imageData = arg->as<QQuickJSContext2DImageData>()) {
+        } else if (QV4::Referenced<QQuickJSContext2DImageData> imageData = arg->asRef<QQuickJSContext2DImageData>()) {
             QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->pixelData.as<QQuickJSContext2DPixelData>());
             if (pix && !pix->image.isNull()) {
                 pixmap.take(new QQuickCanvasPixmap(pix->image, r->context->canvas()->window()));
@@ -3239,7 +3239,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::Simpl
 
     if (ctx->callData->argc == 1) {
         QV4::ScopedValue arg0(scope, ctx->callData->args[0]);
-        if (QQuickJSContext2DImageData *imgData = arg0->as<QQuickJSContext2DImageData>()) {
+        if (QV4::Referenced<QQuickJSContext2DImageData> imgData = arg0->asRef<QQuickJSContext2DImageData>()) {
             QV4::Scoped<QQuickJSContext2DPixelData> pa(scope, imgData->pixelData.as<QQuickJSContext2DPixelData>());
             if (pa) {
                 qreal w = pa->image.width();
@@ -3316,7 +3316,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::SimpleCa
     if (!qIsFinite(dx) || !qIsFinite(dy))
         V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
 
-    QQuickJSContext2DImageData *imageData = arg0->as<QQuickJSContext2DImageData>();
+    QV4::Referenced<QQuickJSContext2DImageData> imageData = arg0->asRef<QQuickJSContext2DImageData>();
     if (!imageData)
         return ctx->callData->thisObject.asReturnedValue();