1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qv4variantobject_p.h"
41#include "qv4functionobject_p.h"
42#include "qv4objectproto_p.h"
43#include <private/qqmlvaluetypewrapper_p.h>
44#include <private/qv4qobjectwrapper_p.h>
45
46QT_BEGIN_NAMESPACE
47
48using namespace QV4;
49
50DEFINE_OBJECT_VTABLE(VariantObject);
51
52void Heap::VariantObject::init()
53{
54 Object::init();
55 scarceData = new ExecutionEngine::ScarceResourceData;
56}
57
58void Heap::VariantObject::init(const QVariant &value)
59{
60 Object::init();
61 scarceData = new ExecutionEngine::ScarceResourceData(value);
62 if (isScarce())
63 removeVmePropertyReference();
64}
65
66bool VariantObject::Data::isScarce() const
67{
68 int t = data().userType();
69 return t == QMetaType::QPixmap || t == QMetaType::QImage;
70}
71
72bool VariantObject::virtualIsEqualTo(Managed *m, Managed *other)
73{
74 Q_ASSERT(m->as<QV4::VariantObject>());
75 QV4::VariantObject *lv = static_cast<QV4::VariantObject *>(m);
76
77 if (QV4::VariantObject *rv = other->as<QV4::VariantObject>())
78 return lv->d()->data() == rv->d()->data();
79
80 if (QV4::QQmlValueTypeWrapper *v = other->as<QQmlValueTypeWrapper>())
81 return v->isEqual(value: lv->d()->data());
82
83 return false;
84}
85
86void VariantObject::addVmePropertyReference() const
87{
88 if (d()->isScarce() && ++d()->vmePropertyReferenceCount == 1) {
89 // remove from the ep->scarceResources list
90 // since it is now no longer eligible to be
91 // released automatically by the engine.
92 d()->addVmePropertyReference();
93 }
94}
95
96void VariantObject::removeVmePropertyReference() const
97{
98 if (d()->isScarce() && --d()->vmePropertyReferenceCount == 0) {
99 // and add to the ep->scarceResources list
100 // since it is now eligible to be released
101 // automatically by the engine.
102 d()->removeVmePropertyReference();
103 }
104}
105
106
107void VariantPrototype::init()
108{
109 defineDefaultProperty(QStringLiteral("preserve"), code: method_preserve, argumentCount: 0);
110 defineDefaultProperty(QStringLiteral("destroy"), code: method_destroy, argumentCount: 0);
111 defineDefaultProperty(name: engine()->id_valueOf(), code: method_valueOf, argumentCount: 0);
112 defineDefaultProperty(name: engine()->id_toString(), code: method_toString, argumentCount: 0);
113}
114
115ReturnedValue VariantPrototype::method_preserve(const FunctionObject *, const Value *thisObject, const Value *, int)
116{
117 const VariantObject *o = thisObject->as<QV4::VariantObject>();
118 if (o && o->d()->isScarce())
119 o->d()->addVmePropertyReference();
120 RETURN_UNDEFINED();
121}
122
123ReturnedValue VariantPrototype::method_destroy(const FunctionObject *, const Value *thisObject, const Value *, int)
124{
125 const VariantObject *o = thisObject->as<QV4::VariantObject>();
126 if (o) {
127 if (o->d()->isScarce())
128 o->d()->addVmePropertyReference();
129 o->d()->data() = QVariant();
130 }
131 RETURN_UNDEFINED();
132}
133
134ReturnedValue VariantPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int)
135{
136 ExecutionEngine *v4 = b->engine();
137 const VariantObject *o = thisObject->as<QV4::VariantObject>();
138 if (!o)
139 RETURN_UNDEFINED();
140 const QVariant variant = o->d()->data();
141 QString result = variant.toString();
142 if (result.isEmpty() && !variant.canConvert(targetTypeId: QMetaType::QString)) {
143 QDebug dbg(&result);
144 dbg << variant;
145 // QDebug appends a space, we're not interested in continuing the stream so we chop it off.
146 // Can't use nospace() because it would affect the debug-stream operator of the variant.
147 result.chop(n: 1);
148 }
149 return Encode(v4->newString(s: result));
150}
151
152ReturnedValue VariantPrototype::method_valueOf(const FunctionObject *b, const Value *thisObject, const Value *, int)
153{
154 const VariantObject *o = thisObject->as<QV4::VariantObject>();
155 if (o) {
156 QVariant v = o->d()->data();
157 switch (v.userType()) {
158 case QMetaType::UnknownType:
159 return Encode::undefined();
160 case QMetaType::QString:
161 return Encode(b->engine()->newString(s: v.toString()));
162 case QMetaType::Int:
163 return Encode(v.toInt());
164 case QMetaType::Double:
165 case QMetaType::UInt:
166 return Encode(v.toDouble());
167 case QMetaType::Bool:
168 return Encode(v.toBool());
169 default:
170 if (QMetaType::typeFlags(type: v.userType()) & QMetaType::IsEnumeration)
171 RETURN_RESULT(Encode(v.toInt()));
172 break;
173 }
174 }
175 return thisObject->asReturnedValue();
176}
177
178QT_END_NAMESPACE
179

source code of qtdeclarative/src/qml/jsruntime/qv4variantobject.cpp