Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmlvaluetypewrapper.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant
4
5
#
include
"qqmlvaluetypewrapper_p.h"
6
7
#
include
<
private
/
qqmlbinding_p
.
h
>
8
#
include
<
private
/
qqmlbuiltinfunctions_p
.
h
>
9
#
include
<
private
/
qqmlvaluetype_p
.
h
>
10
11
#
include
<
private
/
qv4alloca_p
.
h
>
12
#
include
<
private
/
qv4arraybuffer_p
.
h
>
13
#
include
<
private
/
qv4dateobject_p
.
h
>
14
#
include
<
private
/
qv4engine_p
.
h
>
15
#
include
<
private
/
qv4functionobject_p
.
h
>
16
#
include
<
private
/
qv4identifiertable_p
.
h
>
17
#
include
<
private
/
qv4jsonobject_p
.
h
>
18
#
include
<
private
/
qv4lookup_p
.
h
>
19
#
include
<
private
/
qv4qobjectwrapper_p
.
h
>
20
#
include
<
private
/
qv4stackframe_p
.
h
>
21
#
include
<
private
/
qv4variantobject_p
.
h
>
22
23
#
include
<
QtCore
/
qline
.
h
>
24
#
include
<
QtCore
/
qsize
.
h
>
25
#
include
<
QtCore
/
qdatetime
.
h
>
26
#
include
<
QtCore
/
qloggingcategory
.
h
>
27
28
#
if
QT_CONFIG
(
regularexpression
)
29
#
include
<
private
/
qv4regexpobject_p
.
h
>
30
#
endif
31
32
QT_BEGIN_NAMESPACE
33
34
DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeWrapper);
35
36
namespace
QV4
{
37
38
Heap
::
QQmlValueTypeWrapper
*
Heap
::
QQmlValueTypeWrapper
::
detached
()
const
39
{
40
return
internalClass
->
engine
->
memoryManager
->
allocate
<
QV4
::
QQmlValueTypeWrapper
>(
41
m_gadgetPtr
,
QMetaType
(
m_metaType
),
m_metaObject
,
nullptr
, -1,
NoFlag
);
42
}
43
44
void
Heap
::
QQmlValueTypeWrapper
::
destroy
()
45
{
46
metaType
().
destroy
(
m_gadgetPtr
);
47
ReferenceObject
::
destroy
();
48
}
49
50
QVariant
Heap
::
QQmlValueTypeWrapper
::
toVariant
()
const
51
{
52
Q_ASSERT
(
gadgetPtr
());
53
return
QVariant
(
metaType
(),
gadgetPtr
());
54
}
55
56
bool
Heap
::
QQmlValueTypeWrapper
::
setVariant
(
const
QVariant
&
variant
)
57
{
58
Q_ASSERT
(
isVariant
());
59
60
const
QMetaType
variantReferenceType
=
variant
.
metaType
();
61
if
(
variantReferenceType
!=
metaType
()) {
62
// This is a stale VariantReference. That is, the variant has been
63
// overwritten with a different type in the meantime.
64
// We need to modify this reference to the updated value type, if
65
// possible, or return false if it is not a value type.
66
if
(
QQmlMetaType
::
isValueType
(
variantReferenceType
)) {
67
const
QMetaObject
*
mo
=
QQmlMetaType
::
metaObjectForValueType
(
variantReferenceType
);
68
metaType
().
destroy
(
gadgetPtr
());
69
setGadgetPtr
(
nullptr
);
70
setMetaObject
(
mo
);
71
setMetaType
(
variantReferenceType
);
72
if
(!
mo
)
73
return
false
;
74
}
else
{
75
return
false
;
76
}
77
}
78
79
setData
(
variant
.
constData
());
80
return
true
;
81
}
82
83
void
*
Heap
::
QQmlValueTypeWrapper
::
storagePointer
()
84
{
85
if
(!
gadgetPtr
()) {
86
setGadgetPtr
(
metaType
().
create
(
nullptr
));
87
}
88
return
gadgetPtr
();
89
}
90
91
bool
Heap
::
QQmlValueTypeWrapper
::
readReference
()
92
{
93
// If locations are enforced we only read once
94
return
enforcesLocation
() ||
QV4
::
ReferenceObject
::
readReference
(
this
);
95
}
96
97
bool
Heap
::
QQmlValueTypeWrapper
::
writeBack
(
int
propertyIndex
)
98
{
99
return
isAttachedToProperty
() &&
QV4
::
ReferenceObject
::
writeBack
(
this
,
propertyIndex
);
100
}
101
102
ReturnedValue
QQmlValueTypeWrapper
::
create
(
103
ExecutionEngine
*
engine
,
Heap
::
QQmlValueTypeWrapper
*
cloneFrom
,
Heap
::
Object
*
object
)
104
{
105
QV4
::
Scope
scope
(
engine
);
106
initProto
(
engine
);
107
108
// Either we're enforcing the location, then we have to read right away.
109
// Or we don't then we lazy-load. In neither case we pass any data.
110
Scoped
<
QQmlValueTypeWrapper
>
r
(
scope
,
engine
->
memoryManager
->
allocate
<
QQmlValueTypeWrapper
>(
111
nullptr
,
cloneFrom
->
metaType
(),
cloneFrom
->
metaObject
(),
112
object
,
cloneFrom
->
property
(),
cloneFrom
->
flags
()));
113
r
->
d
()->
setLocation
(
cloneFrom
->
function
(),
cloneFrom
->
statementIndex
());
114
if
(
cloneFrom
->
enforcesLocation
())
115
QV4
::
ReferenceObject
::
readReference
(
r
->
d
());
116
return
r
->
asReturnedValue
();
117
}
118
119
void
QQmlValueTypeWrapper
::
initProto
(
ExecutionEngine
*
v4
)
120
{
121
if
(
v4
->
valueTypeWrapperPrototype
()->
d
())
122
return
;
123
124
Scope
scope
(
v4
);
125
ScopedObject
o
(
scope
,
v4
->
newObject
());
126
o
->
defineDefaultProperty
(
v4
->
id_toString
(),
method_toString
, 1);
127
v4
->
jsObjects
[
QV4
::
ExecutionEngine
::
ValueTypeProto
] =
o
->
d
();
128
}
129
130
int
QQmlValueTypeWrapper
::
virtualMetacall
(
131
Object
*
object
,
QMetaObject
::
Call
call
,
int
index
,
void
**
a
)
132
{
133
QQmlValueTypeWrapper
*
wrapper
=
object
->
as
<
QQmlValueTypeWrapper
>();
134
Q_ASSERT
(
wrapper
);
135
136
switch
(
call
) {
137
case
QMetaObject
::
InvokeMetaMethod
:
138
case
QMetaObject
::
ReadProperty
:
139
case
QMetaObject
::
BindableProperty
:
140
case
QMetaObject
::
CustomCall
:
141
if
(
wrapper
->
d
()->
object
())
142
wrapper
->
d
()->
readReference
();
143
break
;
144
default
:
145
break
;
146
}
147
148
const
QMetaObject
*
mo
=
wrapper
->
d
()->
metaObject
();
149
if
(!
mo
->
d
.
static_metacall
)
150
return
0;
151
152
mo
->
d
.
static_metacall
(
static_cast
<
QObject
*>(
wrapper
->
d
()->
gadgetPtr
()),
call
,
index
,
a
);
153
154
switch
(
call
) {
155
case
QMetaObject
::
ReadProperty
:
156
break
;
157
case
QMetaObject
::
WriteProperty
:
158
case
QMetaObject
::
ResetProperty
:
159
if
(
wrapper
->
d
()->
object
())
160
wrapper
->
d
()->
writeBack
(
index
);
161
break
;
162
case
QMetaObject
::
InvokeMetaMethod
:
163
case
QMetaObject
::
CustomCall
:
164
if
(
wrapper
->
d
()->
object
())
165
wrapper
->
d
()->
writeBack
();
166
break
;
167
default
:
168
break
;
169
}
170
171
return
-1;
172
}
173
174
ReturnedValue
QQmlValueTypeWrapper
::
create
(
175
ExecutionEngine
*
engine
,
const
void
*
data
,
const
QMetaObject
*
metaObject
,
QMetaType
type
,
176
Heap
::
Object
*
object
,
int
property
,
Heap
::
ReferenceObject
::
Flags
flags
)
177
{
178
Scope
scope
(
engine
);
179
initProto
(
engine
);
180
181
if
(!
type
.
isValid
()) {
182
return
engine
->
throwTypeError
(
QLatin1String
(
"Type %1 is not a value type"
)
183
.
arg
(
QString
::
fromUtf8
(
type
.
name
())));
184
}
185
186
// If data is given explicitly, we assume it has just been read from the property
187
Scoped
<
QQmlValueTypeWrapper
>
r
(
scope
,
engine
->
memoryManager
->
allocate
<
QQmlValueTypeWrapper
>(
188
data
,
type
,
metaObject
,
object
,
property
,
flags
));
189
if
(
CppStackFrame
*
frame
=
engine
->
currentStackFrame
)
190
r
->
d
()->
setLocation
(
frame
->
v4Function
,
frame
->
statementNumber
());
191
if
(!
data
&&
r
->
d
()->
enforcesLocation
())
192
QV4
::
ReferenceObject
::
readReference
(
r
->
d
());
193
return
r
->
asReturnedValue
();
194
}
195
196
ReturnedValue
QQmlValueTypeWrapper
::
create
(
197
ExecutionEngine
*
engine
,
const
void
*
data
,
const
QMetaObject
*
metaObject
,
QMetaType
type
)
198
{
199
Scope
scope
(
engine
);
200
initProto
(
engine
);
201
202
if
(!
type
.
isValid
()) {
203
return
engine
->
throwTypeError
(
QLatin1String
(
"Type %1 is not a value type"
)
204
.
arg
(
QString
::
fromUtf8
(
type
.
name
())));
205
}
206
207
Scoped
<
QQmlValueTypeWrapper
>
r
(
208
scope
,
engine
->
memoryManager
->
allocate
<
QQmlValueTypeWrapper
>(
209
data
,
type
,
metaObject
,
nullptr
, -1,
Heap
::
ReferenceObject
::
NoFlag
));
210
return
r
->
asReturnedValue
();
211
}
212
213
QVariant
QQmlValueTypeWrapper
::
toVariant
()
const
214
{
215
if
(
d
()->
isReference
() && !
readReferenceValue
())
216
return
QVariant
();
217
return
d
()->
toVariant
();
218
}
219
220
bool
QQmlValueTypeWrapper
::
toGadget
(
void
*
data
)
const
221
{
222
if
(
d
()->
isReference
() && !
readReferenceValue
())
223
return
false
;
224
const
QMetaType
type
=
d
()->
metaType
();
225
type
.
destruct
(
data
);
226
type
.
construct
(
data
,
d
()->
gadgetPtr
());
227
return
true
;
228
}
229
230
bool
QQmlValueTypeWrapper
::
virtualIsEqualTo
(
Managed
*
m
,
Managed
*
other
)
231
{
232
Q_ASSERT
(
m
&&
m
->
as
<
QQmlValueTypeWrapper
>() &&
other
);
233
QV4
::
QQmlValueTypeWrapper
*
lv
=
static_cast
<
QQmlValueTypeWrapper
*>(
m
);
234
235
if
(
QV4
::
VariantObject
*
rv
=
other
->
as
<
VariantObject
>())
236
return
lv
->
isEqual
(
rv
->
d
()->
data
());
237
238
if
(
QV4
::
QQmlValueTypeWrapper
*
v
=
other
->
as
<
QQmlValueTypeWrapper
>())
239
return
lv
->
isEqual
(
v
->
toVariant
());
240
241
return
false
;
242
}
243
244
bool
QQmlValueTypeWrapper
::
virtualHasProperty
(
const
Managed
*
m
,
PropertyKey
id
)
245
{
246
if
(!
id
.
isString
())
247
return
Object
::
virtualHasProperty
(
m
,
id
);
248
Q_ASSERT
(
m
&&
m
->
as
<
QQmlValueTypeWrapper
>());
249
auto
wrapper
=
static_cast
<
const
QQmlValueTypeWrapper
*>(
m
);
250
if
(
auto
mo
=
wrapper
->
d
()->
metaObject
())
251
if
(
mo
->
indexOfProperty
(
id
.
toQString
().
toUtf8
()) != -1)
252
return
true
;
253
254
/* we don't want to fallback to QObject::virtualHasProperty
255
as that would end up calling getOwnProperty which is wasteful,
256
as it calls our own virtualGetOwnProperty.
257
As we know that our own properties are only those found on the meta-object,
258
we can instead skip the call, and simply check whether the property exists
259
on the prototype.
260
*/
261
Scope
scope
(
m
->
engine
());
262
ScopedObject
o
(
scope
,
m
);
263
o
=
o
->
getPrototypeOf
();
264
if
(
o
)
265
return
o
->
hasProperty
(
id
);
266
267
return
false
;
268
}
269
270
static
Heap
::
ReferenceObject
::
Flags
referenceFlags
(
const
QMetaObject *metaObject,
int
index)
271
{
272
return
metaObject->property(index).isWritable()
273
? (Heap::ReferenceObject::CanWriteBack | Heap::ReferenceObject::EnforcesLocation)
274
: Heap::ReferenceObject::EnforcesLocation;
275
}
276
277
static
void
doStaticReadCall
(
278
const
QMetaObject *metaObject, Heap::QQmlValueTypeWrapper *valueTypeWrapper,
279
int
index,
void
**args)
280
{
281
metaObject->d.static_metacall(
282
reinterpret_cast
<QObject*>(
283
valueTypeWrapper->gadgetPtr()), QMetaObject::ReadProperty, index, args);
284
}
285
286
ReturnedValue
QQmlValueTypeWrapper
::
getGadgetProperty
(
287
ExecutionEngine
*
engine
,
Heap
::
QQmlValueTypeWrapper
*
valueTypeWrapper
,
QMetaType
metaType
,
288
quint16
coreIndex
,
bool
isFunction
,
bool
isEnum
)
289
{
290
if
(
isFunction
) {
291
// calling a Q_INVOKABLE function of a value type
292
return
QV4
::
QObjectMethod
::
create
(
engine
,
valueTypeWrapper
,
coreIndex
);
293
}
294
295
const
QMetaObject
*
metaObject
=
valueTypeWrapper
->
metaObject
();
296
int
index
=
coreIndex
;
297
298
const
auto
wrapChar16
= [
engine
](
char16_t
c
) {
299
return
engine
->
newString
(
QChar
(
c
));
300
};
301
const
auto
wrapQObject
= [
engine
](
QObject
*
object
) {
302
return
QObjectWrapper
::
wrap
(
engine
,
object
);
303
};
304
const
auto
wrapJsonValue
= [
engine
](
const
QJsonValue
&
value
) {
305
return
JsonObject
::
fromJsonValue
(
engine
,
value
);
306
};
307
const
auto
wrapJsonObject
= [
engine
](
const
QJsonObject
&
object
) {
308
return
JsonObject
::
fromJsonObject
(
engine
,
object
);
309
};
310
const
auto
wrapJsonArray
= [
engine
](
const
QJsonArray
&
array
) {
311
return
JsonObject
::
fromJsonArray
(
engine
,
array
);
312
};
313
314
const
auto
wrapQDateTime
= [&](
const
QDateTime
&
dateTime
) {
315
return
engine
->
newDateObject
(
316
dateTime
,
valueTypeWrapper
,
index
,
referenceFlags
(
metaObject
,
index
));
317
};
318
const
auto
wrapQDate
= [&](
QDate
date
) {
319
return
engine
->
newDateObject
(
320
date
,
valueTypeWrapper
,
index
,
referenceFlags
(
metaObject
,
index
));
321
};
322
const
auto
wrapQTime
= [&](
QTime
time
) {
323
return
engine
->
newDateObject
(
324
time
,
valueTypeWrapper
,
index
,
referenceFlags
(
metaObject
,
index
));
325
};
326
327
#
define
VALUE_TYPE_LOAD
(
metatype
,
cpptype
,
constructor
)
328
case
metatype
:
{
329
cpptype
v
;
330
void
*
args
[
]
=
{
&
v
,
nullptr
}
;
331
doStaticReadCall
(
metaObject
,
valueTypeWrapper
,
index
,
args
)
;
332
return
QV4
::
Encode
(
constructor
(
v
)
)
;
333
}
334
335
QQmlMetaObject
::
resolveGadgetMethodOrPropertyIndex
(
336
QMetaObject
::
ReadProperty
, &
metaObject
, &
index
);
337
338
const
int
metaTypeId
=
isEnum
339
?
metaType
.
underlyingType
().
id
()
340
: (
metaType
.
flags
() &
QMetaType
::
PointerToQObject
)
341
?
QMetaType
::
QObjectStar
342
:
metaType
.
id
();
343
344
switch
(
metaTypeId
) {
345
case
QMetaType
::
UnknownType
:
346
case
QMetaType
::
Void
:
347
return
Encode
::
undefined
();
348
case
QMetaType
::
Nullptr
:
349
case
QMetaType
::
VoidStar
:
350
return
Encode
::
null
();
351
VALUE_TYPE_LOAD
(
QMetaType
::
Bool
,
bool
,
bool
);
352
VALUE_TYPE_LOAD
(
QMetaType
::
Int
,
int
,
int
);
353
VALUE_TYPE_LOAD
(
QMetaType
::
UInt
,
uint
,
uint
);
354
VALUE_TYPE_LOAD
(
QMetaType
::
Long
,
long
,
double
);
355
VALUE_TYPE_LOAD
(
QMetaType
::
ULong
,
ulong
,
double
);
356
VALUE_TYPE_LOAD
(
QMetaType
::
LongLong
,
qlonglong
,
double
);
357
VALUE_TYPE_LOAD
(
QMetaType
::
ULongLong
,
qulonglong
,
double
);
358
VALUE_TYPE_LOAD
(
QMetaType
::
Double
,
double
,
double
);
359
VALUE_TYPE_LOAD
(
QMetaType
::
QString
,
QString
,
engine
->
newString
);
360
VALUE_TYPE_LOAD
(
QMetaType
::
QByteArray
,
QByteArray
,
engine
->
newArrayBuffer
);
361
VALUE_TYPE_LOAD
(
QMetaType
::
Float
,
float
,
float
);
362
VALUE_TYPE_LOAD
(
QMetaType
::
Short
,
short
,
int
);
363
VALUE_TYPE_LOAD
(
QMetaType
::
UShort
,
unsigned
short
,
int
);
364
VALUE_TYPE_LOAD
(
QMetaType
::
Char
,
char
,
int
);
365
VALUE_TYPE_LOAD
(
QMetaType
::
UChar
,
unsigned
char
,
int
);
366
VALUE_TYPE_LOAD
(
QMetaType
::
SChar
,
signed
char
,
int
);
367
VALUE_TYPE_LOAD
(
QMetaType
::
QChar
,
QChar
,
engine
->
newString
);
368
VALUE_TYPE_LOAD
(
QMetaType
::
Char16
,
char16_t
,
wrapChar16
);
369
VALUE_TYPE_LOAD
(
QMetaType
::
QDateTime
,
QDateTime
,
wrapQDateTime
);
370
VALUE_TYPE_LOAD
(
QMetaType
::
QDate
,
QDate
,
wrapQDate
);
371
VALUE_TYPE_LOAD
(
QMetaType
::
QTime
,
QTime
,
wrapQTime
);
372
#
if
QT_CONFIG
(
regularexpression
)
373
VALUE_TYPE_LOAD
(
QMetaType
::
QRegularExpression
,
QRegularExpression
,
engine
->
newRegExpObject
);
374
#
endif
375
VALUE_TYPE_LOAD
(
QMetaType
::
QObjectStar
,
QObject
*,
wrapQObject
);
376
VALUE_TYPE_LOAD
(
QMetaType
::
QJsonValue
,
QJsonValue
,
wrapJsonValue
);
377
VALUE_TYPE_LOAD
(
QMetaType
::
QJsonObject
,
QJsonObject
,
wrapJsonObject
);
378
VALUE_TYPE_LOAD
(
QMetaType
::
QJsonArray
,
QJsonArray
,
wrapJsonArray
);
379
case
QMetaType
::
QPixmap
:
380
case
QMetaType
::
QImage
: {
381
QVariant
v
(
metaType
);
382
void
*
args
[] = {
v
.
data
(),
nullptr
};
383
doStaticReadCall
(
metaObject
,
valueTypeWrapper
,
index
,
args
);
384
return
Encode
(
engine
->
newVariantObject
(
metaType
,
v
.
data
()));
385
}
386
case
QMetaType
::
QVariant
: {
387
QVariant
v
;
388
void
*
args
[] = { &
v
,
nullptr
};
389
doStaticReadCall
(
metaObject
,
valueTypeWrapper
,
index
,
args
);
390
return
engine
->
fromVariant
(
391
v
,
valueTypeWrapper
,
index
,
392
referenceFlags
(
metaObject
,
index
) |
Heap
::
ReferenceObject
::
IsVariant
);
393
}
394
default
:
395
break
;
396
}
397
398
QVariant
v
(
metaType
);
399
void
*
args
[] = {
v
.
data
(),
nullptr
};
400
doStaticReadCall
(
metaObject
,
valueTypeWrapper
,
index
,
args
);
401
return
engine
->
fromVariant
(
v
,
valueTypeWrapper
,
index
,
referenceFlags
(
metaObject
,
index
));
402
#
undef
VALUE_TYPE_LOAD
403
}
404
405
PropertyAttributes
QQmlValueTypeWrapper
::
virtualGetOwnProperty
(
const
Managed
*
m
,
PropertyKey
id
,
Property
*
p
)
406
{
407
if
(
id
.
isString
()) {
408
const
QQmlValueTypeWrapper
*
r
=
static_cast
<
const
QQmlValueTypeWrapper
*>(
m
);
409
Q_ASSERT
(
r
);
410
411
const
QQmlPropertyData
result
=
r
->
dataForPropertyKey
(
id
);
412
if
(!
result
.
isValid
())
413
return
Attr_Invalid
;
// Property doesn't exist. Object shouldn't meddle with it.
414
415
if
(!
p
)
416
return
Attr_Data
;
// Property exists, but we're not interested in the value
417
418
if
(!
r
->
d
()->
isReference
() ||
r
->
readReferenceValue
()) {
419
// Property exists, and we can retrieve it
420
p
->
value
=
getGadgetProperty
(
421
r
->
engine
(),
r
->
d
(),
result
.
propType
(),
result
.
coreIndex
(),
422
result
.
isFunction
(),
result
.
isEnum
());
423
}
else
{
424
// Property exists, but we can't retrieve it. Make it undefined.
425
p
->
value
=
Encode
::
undefined
();
426
}
427
428
return
Attr_Data
;
429
}
430
431
return
QV4
::
Object
::
virtualGetOwnProperty
(
m
,
id
,
p
);
432
}
433
434
struct
QQmlValueTypeWrapperOwnPropertyKeyIterator
:
ObjectOwnPropertyKeyIterator
435
{
436
int
propertyIndex
= 0;
437
~
QQmlValueTypeWrapperOwnPropertyKeyIterator
()
override
=
default
;
438
PropertyKey
next
(
const
Object *o, Property *pd =
nullptr
, PropertyAttributes *attrs =
nullptr
)
override
;
439
440
};
441
442
PropertyKey
QQmlValueTypeWrapperOwnPropertyKeyIterator
::
next
(
const
Object *o, Property *pd, PropertyAttributes *attrs) {
443
const
QQmlValueTypeWrapper *that =
static_cast
<
const
QQmlValueTypeWrapper *>(o);
444
445
if
(that->d()->isReference() && !that->readReferenceValue())
446
return
PropertyKey::invalid();
447
448
const
QMetaObject *mo = that->d()->metaObject();
449
// We don't return methods, ie. they are not visible when iterating
450
const
int
propertyCount = mo->propertyCount();
451
if
(
propertyIndex
< propertyCount) {
452
Scope scope(that->engine());
453
QMetaProperty p = mo->property(
propertyIndex
);
// TODO: Implement and use QBasicMetaProperty
454
ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(p.name())));
455
++
propertyIndex
;
456
if
(attrs)
457
*attrs = QV4::Attr_Data;
458
if
(pd) {
459
QQmlPropertyData data;
460
data.load(p);
461
pd->value = QQmlValueTypeWrapper::getGadgetProperty(
462
that->engine(), that->d(), data.propType(), data.coreIndex(), data.isFunction(),
463
data.isEnum());
464
}
465
return
propName->toPropertyKey();
466
}
467
468
return
ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
469
}
470
471
472
OwnPropertyKeyIterator
*
QQmlValueTypeWrapper
::
virtualOwnPropertyKeys
(
const
Object
*
m
,
Value
*
target
)
473
{
474
*
target
= *
m
;
475
return
new
QQmlValueTypeWrapperOwnPropertyKeyIterator
;
476
}
477
478
bool
QQmlValueTypeWrapper
::
isEqual
(
const
QVariant
&
value
)
const
479
{
480
if
(
d
()->
isReference
() && !
readReferenceValue
())
481
return
false
;
482
int
id1
=
value
.
metaType
().
id
();
483
QVariant
v
=
d
()->
toVariant
();
484
int
id2
=
v
.
metaType
().
id
();
485
if
(
id1
!=
id2
) {
486
// conversions for weak comparison
487
switch
(
id1
) {
488
case
QMetaType
::
QPoint
:
489
if
(
id2
==
QMetaType
::
QPointF
)
490
return
value
.
value
<
QPointF
>() ==
v
.
value
<
QPointF
>();
491
break
;
492
case
QMetaType
::
QPointF
:
493
if
(
id2
==
QMetaType
::
QPoint
)
494
return
value
.
value
<
QPointF
>() ==
v
.
value
<
QPointF
>();
495
break
;
496
case
QMetaType
::
QRect
:
497
if
(
id2
==
QMetaType
::
QRectF
)
498
return
value
.
value
<
QRectF
>() ==
v
.
value
<
QRectF
>();
499
break
;
500
case
QMetaType
::
QRectF
:
501
if
(
id2
==
QMetaType
::
QRect
)
502
return
value
.
value
<
QRectF
>() ==
v
.
value
<
QRectF
>();
503
break
;
504
case
QMetaType
::
QLine
:
505
if
(
id2
==
QMetaType
::
QLineF
)
506
return
value
.
value
<
QLineF
>() ==
v
.
value
<
QLineF
>();
507
break
;
508
case
QMetaType
::
QLineF
:
509
if
(
id2
==
QMetaType
::
QLine
)
510
return
value
.
value
<
QLineF
>() ==
v
.
value
<
QLineF
>();
511
break
;
512
case
QMetaType
::
QSize
:
513
if
(
id2
==
QMetaType
::
QSizeF
)
514
return
value
.
value
<
QSizeF
>() ==
v
.
value
<
QSizeF
>();
515
break
;
516
case
QMetaType
::
QSizeF
:
517
if
(
id2
==
QMetaType
::
QSize
)
518
return
value
.
value
<
QSizeF
>() ==
v
.
value
<
QSizeF
>();
519
break
;
520
default
:
521
break
;
522
}
523
}
524
return
(
value
==
v
);
525
}
526
527
int
QQmlValueTypeWrapper
::
typeId
()
const
528
{
529
return
d
()->
metaType
().
id
();
530
}
531
532
QMetaType
QQmlValueTypeWrapper
::
type
()
const
533
{
534
return
d
()->
metaType
();
535
}
536
537
bool
QQmlValueTypeWrapper
::
write
(
QObject
*
target
,
int
propertyIndex
)
const
538
{
539
Q_ALLOCA_INIT
();
540
bool
destructGadgetOnExit
=
false
;
541
auto
cleanup
=
qScopeGuard
([&]() {
542
if
(
destructGadgetOnExit
) {
543
d
()->
setDirty
(
true
);
544
d
()->
metaType
().
destruct
(
d
()->
gadgetPtr
());
545
d
()->
setGadgetPtr
(
nullptr
);
546
}
547
});
548
549
Q_ALLOCA_DECLARE
(
void
,
rawPtr
);
550
551
if
(
d
()->
isReference
()) {
552
QT_WARNING_PUSH
553
QT_WARNING_DISABLE_GCC
(
"-Walloca-larger-than="
);
// for size = alignment = 0
554
if
(!
d
()->
gadgetPtr
()) {
555
const
size_t
size
=
d
()->
metaType
().
sizeOf
();
556
const
size_t
alignment
=
d
()->
metaType
().
alignOf
();
557
size_t
space
=
size
+
alignment
- 1;
558
Q_ALLOCA_ASSIGN
(
void
,
rawPtr
,
space
);
559
void
*
alignedPtr
=
std
::
align
(
alignment
,
size
,
rawPtr
,
space
);
560
Q_ASSERT
(
alignedPtr
);
561
d
()->
setGadgetPtr
(
alignedPtr
);
562
d
()->
metaType
().
construct
(
d
()->
gadgetPtr
(),
nullptr
);
563
destructGadgetOnExit
=
true
;
564
}
565
QT_WARNING_POP
566
if
(!
readReferenceValue
())
567
return
false
;
568
}
569
570
int
flags
= 0;
571
int
status
= -1;
572
void
*
a
[] = {
d
()->
gadgetPtr
(),
nullptr
, &
status
, &
flags
};
573
QMetaObject
::
metacall
(
target
,
QMetaObject
::
WriteProperty
,
propertyIndex
,
a
);
574
return
true
;
575
}
576
577
QQmlPropertyData
QQmlValueTypeWrapper
::
dataForPropertyKey
(
PropertyKey
id
)
const
578
{
579
if
(!
id
.
isStringOrSymbol
())
580
return
QQmlPropertyData
{};
581
QByteArray
name
=
id
.
asStringOrSymbol
()->
toQString
().
toUtf8
();
582
const
QMetaObject
*
mo
=
d
()->
metaObject
();
583
QQmlPropertyData
result
;
584
QMetaMethod
metaMethod
=
QMetaObjectPrivate
::
firstMethod
(
mo
,
name
);
585
if
(
metaMethod
.
isValid
()) {
586
result
.
load
(
metaMethod
);
587
}
else
{
588
int
propertyIndex
=
d
()->
metaObject
()->
indexOfProperty
(
name
.
constData
());
589
if
(
propertyIndex
>= 0)
590
result
.
load
(
mo
->
property
(
propertyIndex
));
591
}
592
return
result
;
593
}
594
595
ReturnedValue
QQmlValueTypeWrapper
::
method_toString
(
const
FunctionObject
*
b
,
const
Value
*
thisObject
,
const
Value
*,
int
)
596
{
597
const
Object
*
o
=
thisObject
->
as
<
Object
>();
598
if
(!
o
)
599
return
b
->
engine
()->
throwTypeError
();
600
const
QQmlValueTypeWrapper
*
w
=
o
->
as
<
QQmlValueTypeWrapper
>();
601
if
(!
w
)
602
return
b
->
engine
()->
throwTypeError
();
603
604
if
(
w
->
d
()->
isReference
() && !
w
->
readReferenceValue
())
605
RETURN_UNDEFINED
();
606
607
QString
result
;
608
if
(!
QMetaType
::
convert
(
w
->
d
()->
metaType
(),
w
->
d
()->
gadgetPtr
(),
609
QMetaType
(
QMetaType
::
QString
), &
result
)) {
610
result
=
QString
::
fromUtf8
(
w
->
d
()->
metaType
().
name
()) +
QLatin1Char
(
'('
);
611
const
QMetaObject
*
mo
=
w
->
d
()->
metaObject
();
612
const
int
propCount
=
mo
->
propertyCount
();
613
for
(
int
i
= 0;
i
<
propCount
; ++
i
) {
614
if
(
mo
->
property
(
i
).
isDesignable
()) {
615
QVariant
value
=
mo
->
property
(
i
).
readOnGadget
(
w
->
d
()->
gadgetPtr
());
616
if
(
i
> 0)
617
result
+=
QLatin1String
(
", "
);
618
result
+=
value
.
toString
();
619
}
620
}
621
result
+=
QLatin1Char
(
')'
);
622
}
623
return
Encode
(
b
->
engine
()->
newString
(
result
));
624
}
625
626
ReturnedValue
QQmlValueTypeWrapper
::
virtualResolveLookupGetter
(
const
Object
*
object
,
ExecutionEngine
*
engine
,
627
Lookup
*
lookup
)
628
{
629
PropertyKey
id
=
engine
->
identifierTable
->
asPropertyKey
(
engine
->
currentStackFrame
->
v4Function
->
compilationUnit
->
630
runtimeStrings
[
lookup
->
nameIndex
]);
631
if
(!
id
.
isString
())
632
return
Object
::
virtualResolveLookupGetter
(
object
,
engine
,
lookup
);
633
634
const
QQmlValueTypeWrapper
*
r
=
static_cast
<
const
QQmlValueTypeWrapper
*>(
object
);
635
QV4
::
ExecutionEngine
*
v4
=
r
->
engine
();
636
Scope
scope
(
v4
);
637
ScopedString
name
(
scope
,
id
.
asStringOrSymbol
());
638
639
// Note: readReferenceValue() can change the reference->type.
640
if
(
r
->
d
()->
isReference
() && !
r
->
readReferenceValue
())
641
return
Value
::
undefinedValue
().
asReturnedValue
();
642
643
QQmlPropertyData
result
=
r
->
dataForPropertyKey
(
id
);
644
if
(!
result
.
isValid
())
645
return
QV4
::
Object
::
virtualResolveLookupGetter
(
object
,
engine
,
lookup
);
646
647
lookup
->
qgadgetLookup
.
ic
.
set
(
engine
,
r
->
internalClass
());
648
// & 1 to tell the gc that this is not heap allocated; see markObjects in qv4lookup_p.h
649
lookup
->
qgadgetLookup
.
metaObject
=
quintptr
(
r
->
d
()->
metaObject
()) + 1;
650
lookup
->
qgadgetLookup
.
metaType
=
result
.
propType
().
iface
();
651
lookup
->
qgadgetLookup
.
coreIndex
=
result
.
coreIndex
();
652
lookup
->
qgadgetLookup
.
isFunction
=
result
.
isFunction
();
653
lookup
->
qgadgetLookup
.
isEnum
=
result
.
isEnum
();
654
lookup
->
call
=
Lookup
::
Call
::
GetterValueTypeProperty
;
655
return
lookup
->
getter
(
engine
, *
object
);
656
}
657
658
bool
QQmlValueTypeWrapper
::
virtualResolveLookupSetter
(
Object
*
object
,
ExecutionEngine
*
engine
,
Lookup
*
lookup
,
659
const
Value
&
value
)
660
{
661
return
Object
::
virtualResolveLookupSetter
(
object
,
engine
,
lookup
,
value
);
662
}
663
664
ReturnedValue
QQmlValueTypeWrapper
::
virtualGet
(
const
Managed
*
m
,
PropertyKey
id
,
const
Value
*
receiver
,
bool
*
hasProperty
)
665
{
666
Q_ASSERT
(
m
->
as
<
QQmlValueTypeWrapper
>());
667
668
if
(!
id
.
isString
())
669
return
Object
::
virtualGet
(
m
,
id
,
receiver
,
hasProperty
);
670
671
const
QQmlValueTypeWrapper
*
r
=
static_cast
<
const
QQmlValueTypeWrapper
*>(
m
);
672
QV4
::
ExecutionEngine
*
v4
=
r
->
engine
();
673
674
// Note: readReferenceValue() can change the reference->type.
675
if
(
r
->
d
()->
isReference
() && !
r
->
readReferenceValue
())
676
return
Value
::
undefinedValue
().
asReturnedValue
();
677
678
QQmlPropertyData
result
=
r
->
dataForPropertyKey
(
id
);
679
if
(!
result
.
isValid
())
680
return
Object
::
virtualGet
(
m
,
id
,
receiver
,
hasProperty
);
681
682
if
(
hasProperty
)
683
*
hasProperty
=
true
;
684
685
return
getGadgetProperty
(
v4
,
r
->
d
(),
result
.
propType
(),
result
.
coreIndex
(),
result
.
isFunction
(),
result
.
isEnum
());
686
}
687
688
bool
QQmlValueTypeWrapper
::
virtualPut
(
Managed
*
m
,
PropertyKey
id
,
const
Value
&
value
,
Value
*
receiver
)
689
{
690
if
(!
id
.
isString
())
691
return
Object
::
virtualPut
(
m
,
id
,
value
,
receiver
);
692
693
Q_ASSERT
(
m
->
as
<
QQmlValueTypeWrapper
>());
694
ExecutionEngine
*
v4
=
static_cast
<
QQmlValueTypeWrapper
*>(
m
)->
engine
();
695
Scope
scope
(
v4
);
696
if
(
scope
.
hasException
())
697
return
false
;
698
699
Scoped
<
QQmlValueTypeWrapper
>
r
(
scope
,
static_cast
<
QQmlValueTypeWrapper
*>(
m
));
700
Heap
::
Object
*
heapObject
=
nullptr
;
701
if
(
r
->
d
()->
isReference
()) {
702
heapObject
=
r
->
d
()->
object
();
703
if
(!
r
->
readReferenceValue
() || !
r
->
d
()->
canWriteBack
())
704
return
false
;
705
}
706
707
const
QMetaObject
*
metaObject
=
r
->
d
()->
metaObject
();
708
const
QQmlPropertyData
pd
=
r
->
dataForPropertyKey
(
id
);
709
if
(!
pd
.
isValid
())
710
return
false
;
711
712
if
(
heapObject
) {
713
QObject
*
referenceObject
=
nullptr
;
714
QV4
::
ScopedFunctionObject
f
(
scope
,
value
);
715
const
int
referencePropertyIndex
=
r
->
d
()->
property
();
716
QV4
::
Scoped
<
QV4
::
QObjectWrapper
>
o
(
scope
,
heapObject
);
717
if
(
o
) {
718
referenceObject
=
o
->
object
();
719
}
else
{
720
QV4
::
Scoped
<
QV4
::
QQmlTypeWrapper
>
t
(
scope
,
heapObject
);
721
if
(
t
)
722
referenceObject
=
t
->
object
();
723
}
724
725
if
(
f
) {
726
if
(!
f
->
isBinding
()) {
727
// assigning a JS function to a non-var-property is not allowed.
728
QString
error
=
QStringLiteral
(
"Cannot assign JavaScript function to value-type property"
);
729
ScopedString
e
(
scope
,
v4
->
newString
(
error
));
730
v4
->
throwError
(
e
);
731
return
false
;
732
}
733
734
if
(!
referenceObject
) {
735
QString
error
=
QStringLiteral
(
"Cannot create binding on nested value type property"
);
736
ScopedString
e
(
scope
,
v4
->
newString
(
error
));
737
v4
->
throwError
(
e
);
738
return
false
;
739
}
740
741
const
QMetaProperty
writebackProperty
742
=
referenceObject
->
metaObject
()->
property
(
referencePropertyIndex
);
743
const
QMetaType
writeBackPropertyType
=
writebackProperty
.
metaType
();
744
745
QQmlRefPointer
<
QQmlContextData
>
context
=
v4
->
callingQmlContext
();
746
747
QQmlPropertyData
cacheData
;
748
cacheData
.
setWritable
(
true
);
749
cacheData
.
setPropType
(
writeBackPropertyType
);
750
cacheData
.
setCoreIndex
(
referencePropertyIndex
);
751
752
QV4
::
Scoped
<
QQmlBindingFunction
>
bindingFunction
(
scope
, (
const
Value
&)
f
);
753
754
QV4
::
Scoped
<
JavaScriptFunctionObject
>
f
(
scope
,
bindingFunction
->
bindingFunction
());
755
QV4
::
ScopedContext
ctx
(
scope
,
f
->
scope
());
756
QQmlBinding
*
newBinding
=
QQmlBinding
::
create
(&
cacheData
,
f
->
function
(),
referenceObject
,
context
,
ctx
);
757
newBinding
->
setSourceLocation
(
bindingFunction
->
currentLocation
());
758
if
(
f
->
isBoundFunction
())
759
newBinding
->
setBoundFunction
(
static_cast
<
QV4
::
BoundFunction
*>(
f
.
getPointer
()));
760
newBinding
->
setSourceLocation
(
bindingFunction
->
currentLocation
());
761
newBinding
->
setTarget
(
referenceObject
,
cacheData
, &
pd
);
762
QQmlPropertyPrivate
::
setBinding
(
newBinding
);
763
return
true
;
764
}
else
if
(
referenceObject
) {
765
if
(
Q_UNLIKELY
(
lcBuiltinsBindingRemoval
().
isInfoEnabled
())) {
766
if
(
auto
binding
=
QQmlPropertyPrivate
::
binding
(
767
referenceObject
,
768
QQmlPropertyIndex
(
referencePropertyIndex
,
pd
.
coreIndex
()));
769
binding
&& !
binding
->
isSticky
()) {
770
Q_ASSERT
(
binding
->
kind
() ==
QQmlAbstractBinding
::
QmlBinding
);
771
const
auto
qmlBinding
=
static_cast
<
const
QQmlBinding
*>(
binding
);
772
const
auto
stackFrame
=
v4
->
currentStackFrame
;
773
qCInfo
(
lcBuiltinsBindingRemoval
,
774
"Overwriting binding on %s::%s which was initially bound at %s by setting \"%s\" at %s:%d"
,
775
referenceObject
->
metaObject
()->
className
(),
referenceObject
->
metaObject
()->
property
(
referencePropertyIndex
).
name
(),
776
qPrintable
(
qmlBinding
->
expressionIdentifier
()),
777
metaObject
->
property
(
pd
.
coreIndex
()).
name
(),
778
qPrintable
(
stackFrame
->
source
()),
stackFrame
->
lineNumber
());
779
}
780
}
781
QQmlPropertyPrivate
::
removeBinding
(
782
referenceObject
,
QQmlPropertyIndex
(
referencePropertyIndex
,
pd
.
coreIndex
()));
783
}
784
}
785
786
QMetaProperty
property
=
metaObject
->
property
(
pd
.
coreIndex
());
787
Q_ASSERT
(
property
.
isValid
());
788
if
(
value
.
isUndefined
() &&
pd
.
isResettable
()) {
789
property
.
resetOnGadget
(
reinterpret_cast
<
QObject
*>(
r
->
d
()->
gadgetPtr
()));
790
if
(
heapObject
)
791
r
->
d
()->
writeBack
(
pd
.
coreIndex
());
792
return
true
;
793
}
794
795
QVariant
v
=
QV4
::
ExecutionEngine
::
toVariant
(
value
,
property
.
metaType
());
796
797
if
(
property
.
isEnumType
() && (
QMetaType
::
Type
)
v
.
userType
() ==
QMetaType
::
Double
)
798
v
=
v
.
toInt
();
799
800
void
*
gadget
=
r
->
d
()->
gadgetPtr
();
801
const
QMetaType
type
=
v
.
metaType
();
802
if
(!
property
.
writeOnGadget
(
gadget
,
std
::
move
(
v
))) {
803
const
QString
error
=
QLatin1String
(
"Cannot assign "
) +
804
QLatin1String
(
type
.
name
()) +
805
QLatin1String
(
" to "
) +
806
QLatin1String
(
property
.
metaType
().
name
());
807
scope
.
engine
->
throwError
(
error
);
808
return
true
;
809
}
810
811
if
(
heapObject
)
812
r
->
d
()->
writeBack
(
pd
.
coreIndex
());
813
814
return
true
;
815
}
816
817
}
// namespace QV4
818
819
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QV4
Definition
qjsvalue.h:24
QV4::referenceFlags
static Heap::ReferenceObject::Flags referenceFlags(const QMetaObject *metaObject, int index)
Definition
qqmlvaluetypewrapper.cpp:270
QV4::doStaticReadCall
static void doStaticReadCall(const QMetaObject *metaObject, Heap::QQmlValueTypeWrapper *valueTypeWrapper, int index, void **args)
Definition
qqmlvaluetypewrapper.cpp:277
VALUE_TYPE_LOAD
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor)
QV4::QQmlValueTypeWrapperOwnPropertyKeyIterator
Definition
qqmlvaluetypewrapper.cpp:435
QV4::QQmlValueTypeWrapperOwnPropertyKeyIterator::next
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
Definition
qqmlvaluetypewrapper.cpp:442
QV4::QQmlValueTypeWrapperOwnPropertyKeyIterator::~QQmlValueTypeWrapperOwnPropertyKeyIterator
~QQmlValueTypeWrapperOwnPropertyKeyIterator() override=default
QV4::QQmlValueTypeWrapperOwnPropertyKeyIterator::propertyIndex
int propertyIndex
Definition
qqmlvaluetypewrapper.cpp:436
qtdeclarative
src
qml
qml
qqmlvaluetypewrapper.cpp
Generated on
for Qt by
1.18.0