Add support for variant properties in V4
authorMatthew Vogt <matthew.vogt@nokia.com>
Thu, 29 Mar 2012 23:09:51 +0000 (09:09 +1000)
committerQt by Nokia <qt-info@nokia.com>
Sun, 15 Apr 2012 23:26:12 +0000 (01:26 +0200)
Support initialization of variant properties in V4.  Variants can
be set to contain basic types in V4, but we can't extract data from
them since they may contain data types that V4 does not comprehend.

Task-number: QTBUG-25022
Change-Id: I1935d77b50c5a3481c4c8ddd86b9d3d970571217
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
src/qml/qml/v4/qv4bindings.cpp
src/qml/qml/v4/qv4compiler.cpp
src/qml/qml/v4/qv4instruction.cpp
src/qml/qml/v4/qv4instruction_p.h
src/qml/qml/v4/qv4ir.cpp
src/qml/qml/v4/qv4ir_p.h
src/qml/qml/v4/qv4irbuilder.cpp
tests/auto/qml/v4/data/variantHandling.qml [new file with mode: 0644]
tests/auto/qml/v4/tst_v4.cpp

index e5d98e6..db015b0 100644 (file)
@@ -456,7 +456,7 @@ static void testBindingResult(const QString &binding, int line, int column,
     if (expression.hasError()) {
         iserror = true;
         qtscriptResult = "exception";
-    } else if (value.userType() != resultType) {
+    } else if ((value.userType() != resultType) && (resultType != QMetaType::QVariant)) {
         // Override the QMetaType conversions to make them more JS friendly.
         if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString ||
                                                         resultType == QMetaType::QUrl)) {
@@ -506,6 +506,12 @@ static void testBindingResult(const QString &binding, int line, int column,
         case QMetaType::Double:
             v4value = result.getnumber();
             break;
+        case QMetaType::QColor:
+            v4value = *result.getcolorptr();
+            break;
+        case QMetaType::QVariant:
+            v4value = *result.getvariantptr();
+            break;
         default:
             if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
                 v4value = QVariant(QQmlMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
@@ -882,6 +888,19 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertBoolToString, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertBoolToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            new (output.getvariantptr()) QVariant(src.getbool());
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertBoolToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -906,13 +925,26 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
         Register &output = registers[instr->unaryop.output];
         if (src.isUndefined()) {
             output.setUndefined();
-        } else { 
+        } else {
             new (output.getstringptr()) QString(QString::number(src.getint()));
             STRING_REGISTER(instr->unaryop.output);
         }
     }
     QML_V4_END_INSTR(ConvertIntToString, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertIntToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            new (output.getvariantptr()) QVariant(src.getint());
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertIntToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertNumberToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -945,6 +977,19 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertNumberToString, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertNumberToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            new (output.getvariantptr()) QVariant(src.getnumber());
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertNumberToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -1048,6 +1093,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertStringToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QString tmp(*src.getstringptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupString();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            new (output.getvariantptr()) QVariant(tmp);
+
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertStringToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -1085,6 +1149,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertUrlToString, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertUrlToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QUrl tmp(*src.geturlptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupUrl();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            new (output.getvariantptr()) QVariant(tmp);
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertUrlToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -1119,6 +1202,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertColorToString, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertColorToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QColor tmp(*src.getcolorptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupColor();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            new (output.getvariantptr()) QVariant(tmp);
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertColorToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertObjectToBool, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
@@ -1131,6 +1233,20 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertObjectToBool, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertObjectToVariant, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined())
+            output.setUndefined();
+        else {
+            new (output.getvariantptr()) QVariant(qVariantFromValue<QObject *>(src.getQObject()));
+            VARIANT_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertObjectToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ConvertNullToObject, unaryop)
     {
         Register &output = registers[instr->unaryop.output];
@@ -1138,6 +1254,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertNullToObject, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertNullToVariant, unaryop)
+    {
+        Register &output = registers[instr->unaryop.output];
+        new (output.getvariantptr()) QVariant();
+        VARIANT_REGISTER(instr->unaryop.output);
+    }
+    QML_V4_END_INSTR(ConvertNullToVariant, unaryop)
+
     QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];
index 045a14f..e03270c 100644 (file)
@@ -377,6 +377,9 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
         case QMetaType::QColor:
             regType = QColorType;
             break;
+        case QMetaType::QVariant:
+            regType = QVariantType;
+            break;
 
         default:
             if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
@@ -966,6 +969,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
             switch (targetTy) {
             case IR::BoolType:
             case IR::StringType:
+            case IR::VariantType:
                 // nothing to do. V4 will generate optimized
                 // url-to-xxx conversions.
                 break;
@@ -1068,6 +1072,20 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
             case IR::NullType: opcode = V4Instr::ConvertNullToObject; break;
             default: break;
             } // switch
+        } else if (targetTy == IR::VariantType) {
+            if (s->isMoveForReturn) {
+                switch (sourceTy) {
+                case IR::BoolType: opcode = V4Instr::ConvertBoolToVariant; break;
+                case IR::IntType:  opcode = V4Instr::ConvertIntToVariant; break;
+                case IR::NumberType: opcode = V4Instr::ConvertNumberToVariant; break;
+                case IR::UrlType: opcode = V4Instr::ConvertUrlToVariant; break;
+                case IR::ColorType: opcode = V4Instr::ConvertColorToVariant; break;
+                case IR::StringType: opcode = V4Instr::ConvertStringToVariant; break;
+                case IR::ObjectType: opcode = V4Instr::ConvertObjectToVariant; break;
+                case IR::NullType: opcode = V4Instr::ConvertNullToVariant; break;
+                default: break;
+                } // switch
+            }
         }
         if (opcode != V4Instr::Noop) {
             V4Instr conv;
@@ -1141,6 +1159,9 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
         case IR::ObjectType:
             test.regType = QMetaType::QObjectStar;
             break;
+        case IR::VariantType:
+            test.regType = QMetaType::QVariant;
+            break;
         case IR::BoolType:
             test.regType = QMetaType::Bool;
             break;
index ecd4f01..c202979 100644 (file)
@@ -144,6 +144,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
     case V4Instr::ConvertBoolToString:
         INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertBoolToVariant:
+        INSTR_DUMP << "\t" << "ConvertBoolToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertIntToBool:
         INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
@@ -153,6 +156,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
     case V4Instr::ConvertIntToString:
         INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertIntToVariant:
+        INSTR_DUMP << "\t" << "ConvertIntToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertNumberToBool:
         INSTR_DUMP << "\t" << "ConvertNumberToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
@@ -162,6 +168,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
     case V4Instr::ConvertNumberToString:
         INSTR_DUMP << "\t" << "ConvertNumberToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertNumberToVariant:
+        INSTR_DUMP << "\t" << "ConvertNumberToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertStringToBool:
         INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
@@ -177,24 +186,39 @@ void Bytecode::dump(const V4Instr *i, int address) const
     case V4Instr::ConvertStringToColor:
         INSTR_DUMP << "\t" << "ConvertStringToColor" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertStringToVariant:
+        INSTR_DUMP << "\t" << "ConvertStringToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertUrlToBool:
         INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
     case V4Instr::ConvertUrlToString:
         INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertUrlToVariant:
+        INSTR_DUMP << "\t" << "ConvertUrlToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertColorToBool:
         INSTR_DUMP << "\t" << "ConvertColorToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
     case V4Instr::ConvertColorToString:
         INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertColorToVariant:
+        INSTR_DUMP << "\t" << "ConvertColorToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertObjectToBool:
         INSTR_DUMP << "\t" << "ConvertObjectToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertObjectToVariant:
+        INSTR_DUMP << "\t" << "ConvertObjectToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ConvertNullToObject:
         INSTR_DUMP << "\t" << "ConvertNullToObject" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
+    case V4Instr::ConvertNullToVariant:
+        INSTR_DUMP << "\t" << "ConvertNullToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+        break;
     case V4Instr::ResolveUrl:
         INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
         break;
index 310bfba..6eb9efa 100644 (file)
@@ -83,23 +83,31 @@ QT_BEGIN_NAMESPACE
     F(ConvertBoolToInt, unaryop) \
     F(ConvertBoolToNumber, unaryop) \
     F(ConvertBoolToString, unaryop) \
+    F(ConvertBoolToVariant, unaryop) \
     F(ConvertIntToBool, unaryop) \
     F(ConvertIntToNumber, unaryop) \
     F(ConvertIntToString, unaryop) \
+    F(ConvertIntToVariant, unaryop) \
     F(ConvertNumberToBool, unaryop) \
     F(ConvertNumberToInt, unaryop) \
     F(ConvertNumberToString, unaryop) \
+    F(ConvertNumberToVariant, unaryop) \
     F(ConvertStringToBool, unaryop) \
     F(ConvertStringToInt, unaryop) \
     F(ConvertStringToNumber, unaryop) \
     F(ConvertStringToUrl, unaryop) \
     F(ConvertStringToColor, unaryop) \
+    F(ConvertStringToVariant, unaryop) \
     F(ConvertUrlToBool, unaryop) \
     F(ConvertUrlToString, unaryop) \
+    F(ConvertUrlToVariant, unaryop) \
     F(ConvertColorToBool, unaryop) \
     F(ConvertColorToString, unaryop) \
+    F(ConvertColorToVariant, unaryop) \
     F(ConvertObjectToBool, unaryop) \
+    F(ConvertObjectToVariant, unaryop) \
     F(ConvertNullToObject, unaryop) \
+    F(ConvertNullToVariant, unaryop) \
     F(ResolveUrl, unaryop) \
     F(MathSinNumber, unaryop) \
     F(MathCosNumber, unaryop) \
index ba0faec..45e909f 100644 (file)
@@ -63,6 +63,8 @@ const char *typeName(Type t)
     case SGAnchorLineType: return "SGAnchorLine";
     case AttachType: return "AttachType";
     case ObjectType: return "object";
+    case VariantType: return "variant";
+    case VarType: return "var";
     case BoolType: return "bool";
     case IntType: return "int";
     case FloatType: return "float";
index 26bd43c..254b810 100644 (file)
@@ -146,6 +146,8 @@ enum Type {
     SGAnchorLineType,
     AttachType,
     ObjectType,
+    VariantType,
+    VarType,
 
     FirstNumberType,
     BoolType = FirstNumberType,
index 31ed9a5..82da09f 100644 (file)
@@ -116,8 +116,16 @@ bool QV4IRBuilder::operator()(QQmlJS::IR::Function *function,
 
     //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
     if (r.code) {
-        const QMetaObject *m = 0;
-        const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
+        IR::Type targetType = IR::InvalidType;
+
+        // This is the only operation where variant is supported:
+        QQmlPropertyData *data = &m_expression->property->core;
+        if (data->propType == QMetaType::QVariant) {
+            targetType = (data->isVMEProperty() ? IR::VarType : IR::VariantType);
+        } else {
+            targetType = irTypeFromVariantType(data->propType, m_engine, 0);
+        }
+
         if (targetType != r.type()) {
             IR::Expr *x = _block->TEMP(targetType);
             _block->MOVE(x, r, true);
diff --git a/tests/auto/qml/v4/data/variantHandling.qml b/tests/auto/qml/v4/data/variantHandling.qml
new file mode 100644 (file)
index 0000000..3d48eef
--- /dev/null
@@ -0,0 +1,67 @@
+import QtQuick 2.0
+
+QtObject {
+    property bool pBool: true
+    property int pInt: 666
+    property real pReal: 3.1415927
+    property string pString: 'foo'
+    property url pUrl: 'http://tools.ietf.org/html/rfc3986#section-1.1.2'
+    property color pColor: Qt.rgba(1, 0, 0, 0.5)
+    property QtObject pObject: QtObject { property string foo: 'bar' }
+
+    // Test assignment to variant
+    property variant pBoolVar: pBool
+    property variant pIntVar: pInt
+    property variant pRealVar: pReal
+    property variant pStringVar: pString
+    property variant pUrlVar: pUrl
+    property variant pColorVar: pColor
+    property variant pObjectVar: pObject
+    property variant pNullVar: null
+    property variant pVarVar: pUrlVar
+
+    // Test equivalence
+    property bool boolConversionSuccess: (pBoolVar == true)
+    property bool intConversionSuccess: (pIntVar == 666)
+    property bool realConversionSuccess: (pRealVar == 3.1415927)
+    property bool stringConversionSuccess: (pStringVar == 'foo')
+
+    property url comparisonUrl: 'http://tools.ietf.org/html/rfc3986#section-1.1.2'
+    property bool urlConversionSuccess: (pUrlVar == comparisonUrl)
+
+    property color comparisonColor: Qt.rgba(1, 0, 0, 0.5)
+    property bool colorConversionSuccess: (pColorVar == comparisonColor)
+
+    property bool objectConversionSuccess: (pObjectVar == pObject)
+    property bool nullConversionSuccess: (pNullVar == null)
+
+    property bool variantConversionSuccess: (pVarVar == comparisonUrl)
+
+    // Operations are not handled by V4 - they should pass through correctly
+    property variant pVarNot: !pBoolVar
+    property variant pVarComplement: ~pIntVar
+    property variant pVarEqual: (pBoolVar == pBoolVar)
+    property variant pVarLiteralEqual: (pBoolVar == true)
+    property variant pVarUnequal: (pUrlVar == pColorVar)
+    property variant pVarComparison: (pIntVar <= pIntVar)
+    property variant pVarShift: (pIntVar >> 1)
+
+    Component.onCompleted: {
+        if (!boolConversionSuccess) console.warn('QV4: bool conversion failed');
+        if (!intConversionSuccess) console.warn('QV4: int conversion failed');
+        if (!realConversionSuccess) console.warn('QV4: real conversion failed');
+        if (!stringConversionSuccess) console.warn('QV4: string conversion failed');
+        if (!urlConversionSuccess) console.warn('QV4: url conversion failed');
+        if (!colorConversionSuccess) console.warn('QV4: color conversion failed');
+        if (!objectConversionSuccess) console.warn('QV4: object conversion failed');
+        if (!nullConversionSuccess) console.warn('QV4: null conversion failed');
+        if (!variantConversionSuccess) console.warn('QV4: variant conversion failed');
+        if (pVarNot != false) console.warn('QV4: variant negation impeded');
+        if (pVarComplement != ~666) console.warn('QV4: variant complement impeded');
+        if (pVarEqual != true) console.warn('QV4: variant equality impeded');
+        if (pVarLiteralEqual != true) console.warn('QV4: variant/literal equality impeded');
+        if (pVarUnequal != false) console.warn('QV4: variant unequality impeded');
+        if (pVarComparison != true) console.warn('QV4: variant comparison impeded');
+        if (pVarShift != 333) console.warn('QV4: variant shift impeded');
+    }
+}
index dfb7cc4..99a4405 100644 (file)
@@ -150,6 +150,7 @@ void tst_v4::qtscript_data()
     QTest::newRow("conversion from string") << "conversions.6.qml"; // QTBUG-24706
     QTest::newRow("conversion from url") << "conversions.7.qml"; // QTBUG-24706
     QTest::newRow("conversion from vec3") << "conversions.8.qml";
+    QTest::newRow("variantHandling") << "variantHandling.qml";
 }
 
 void tst_v4::unnecessaryReeval()
@@ -856,23 +857,31 @@ void tst_v4::debuggingDumpInstructions()
     expectedPreAddress << "\t\tConvertBoolToInt\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertBoolToNumber\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertBoolToString\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertBoolToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertIntToBool\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertIntToNumber\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertIntToString\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertIntToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertNumberToBool\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertNumberToInt\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertNumberToString\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertNumberToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertStringToBool\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertStringToInt\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertStringToNumber\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertStringToUrl\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertStringToColor\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertStringToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertUrlToBool\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertUrlToString\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertUrlToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertColorToBool\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertColorToString\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertColorToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertObjectToBool\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertObjectToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tConvertNullToObject\tInput_Reg(0) -> Output_Reg(0)";
+    expectedPreAddress << "\t\tConvertNullToVariant\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tResolveUrl\t\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tMathSinNumber\t\tInput_Reg(0) -> Output_Reg(0)";
     expectedPreAddress << "\t\tMathCosNumber\t\tInput_Reg(0) -> Output_Reg(0)";