Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4function.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
"qv4function_p.h"
6
7
#
include
<
private
/
qqmlpropertycachecreator_p
.
h
>
8
#
include
<
private
/
qqmltype_p_p
.
h
>
9
10
#
include
<
private
/
qv4engine_p
.
h
>
11
#
include
<
private
/
qv4functiontable_p
.
h
>
12
#
include
<
private
/
qv4identifiertable_p
.
h
>
13
#
include
<
private
/
qv4jscall_p
.
h
>
14
#
include
<
private
/
qv4vme_moth_p
.
h
>
15
16
#
include
<
assembler
/
MacroAssemblerCodeRef
.
h
>
17
18
QT_BEGIN_NAMESPACE
19
20
namespace
QV4
{
21
22
bool
Function
::
call
(
QObject
*
thisObject
,
void
**
a
,
const
QMetaType
*
types
,
int
argc
,
23
ExecutionContext
*
context
)
24
{
25
if
(
kind
!=
AotCompiled
) {
26
return
QV4
::
convertAndCall
(
27
context
->
engine
(),
thisObject
,
a
,
types
,
argc
,
28
[
this
,
context
](
const
Value
*
thisObject
,
const
Value
*
argv
,
int
argc
) {
29
return
call
(
thisObject
,
argv
,
argc
,
context
);
30
});
31
}
32
33
ExecutionEngine
*
engine
=
context
->
engine
();
34
MetaTypesStackFrame
frame
;
35
frame
.
init
(
this
,
thisObject
,
context
,
a
,
types
,
argc
);
36
frame
.
push
(
engine
);
37
Moth
::
VME
::
exec
(&
frame
,
engine
);
38
frame
.
pop
(
engine
);
39
return
!
frame
.
isReturnValueUndefined
();
40
}
41
42
static
ReturnedValue
doCall
(
43
QV4
::
Function
*
self
,
const
QV4
::
Value
*
thisObject
,
const
QV4
::
Value
*
argv
,
int
argc
,
44
QV4
::
ExecutionContext
*
context
)
45
{
46
ExecutionEngine
*
engine
=
context
->
engine
();
47
JSTypesStackFrame
frame
;
48
frame
.
init
(
self
,
argv
,
argc
);
49
frame
.
setupJSFrame
(
engine
->
jsStackTop
,
Value
::
undefinedValue
(),
context
->
d
(),
50
thisObject
? *
thisObject
:
Value
::
undefinedValue
());
51
engine
->
jsStackTop
+=
frame
.
requiredJSStackFrameSize
();
52
frame
.
push
(
engine
);
53
ReturnedValue
result
=
Moth
::
VME
::
exec
(&
frame
,
engine
);
54
frame
.
pop
(
engine
);
55
return
result
;
56
}
57
58
ReturnedValue
Function
::
call
(
59
const
Value
*
thisObject
,
const
Value
*
argv
,
int
argc
,
ExecutionContext
*
context
) {
60
switch
(
kind
) {
61
case
AotCompiled
: {
62
const
auto
&
types
=
aotCompiledFunction
.
types
;
63
return
QV4
::
convertAndCall
(
64
context
->
engine
(),
types
.
data
(),
types
.
length
(),
argv
,
argc
,
65
[
this
,
context
,
thisObject
](
void
**
a
,
const
QMetaType
*
types
,
int
argc
) {
66
call
(
QV4
::
cppThisObject
(
thisObject
),
a
,
types
,
argc
,
context
);
67
});
68
}
69
case
JsTyped
:
70
return
QV4
::
coerceAndCall
(
71
context
->
engine
(), &
jsTypedFunction
,
compiledFunction
,
argv
,
argc
,
72
[
this
,
context
,
thisObject
](
const
Value
*
argv
,
int
argc
) {
73
return
doCall
(
this
,
thisObject
,
argv
,
argc
,
context
);
74
});
75
default
:
76
break
;
77
}
78
79
return
doCall
(
this
,
thisObject
,
argv
,
argc
,
context
);
80
}
81
82
Function
*
Function
::
create
(
ExecutionEngine
*
engine
,
ExecutableCompilationUnit
*
unit
,
83
const
CompiledData
::
Function
*
function
,
84
const
QQmlPrivate
::
AOTCompiledFunction
*
aotFunction
)
85
{
86
return
new
Function
(
engine
,
unit
,
function
,
aotFunction
);
87
}
88
89
void
Function
::
destroy
()
90
{
91
delete
this
;
92
}
93
94
void
Function
::
mark
(
MarkStack
*
ms
)
95
{
96
if
(
internalClass
)
97
internalClass
->
mark
(
ms
);
98
}
99
100
static
bool
isSpecificType
(
const
CompiledData::ParameterType &type)
101
{
102
return
type.typeNameIndexOrCommonType()
103
!= (type.indexIsCommonType() ? quint32(CompiledData::CommonType::Invalid) : 0);
104
}
105
106
Function
::
Function
(
ExecutionEngine
*
engine
,
ExecutableCompilationUnit
*
unit
,
107
const
CompiledData
::
Function
*
function
,
108
const
QQmlPrivate
::
AOTCompiledFunction
*
aotFunction
)
109
:
FunctionData
(
engine
,
unit
)
110
,
compiledFunction
(
function
)
111
,
codeData
(
function
->
code
())
112
{
113
Scope
scope
(
engine
);
114
Scoped
<
InternalClass
>
ic
(
scope
,
engine
->
internalClasses
(
EngineBase
::
Class_CallContext
));
115
116
// first locals
117
const
quint32_le
*
localsIndices
=
compiledFunction
->
localsTable
();
118
for
(
quint32
i
= 0;
i
<
compiledFunction
->
nLocals
; ++
i
)
119
ic
=
ic
->
addMember
(
engine
->
identifierTable
->
asPropertyKey
(
compilationUnit
->
runtimeStrings
[
localsIndices
[
i
]]),
Attr_NotConfigurable
);
120
121
const
CompiledData
::
Parameter
*
formalsIndices
=
compiledFunction
->
formalsTable
();
122
bool
enforceJsTypes
= !
unit
->
ignoresFunctionSignature
();
123
124
for
(
quint32
i
= 0;
i
<
compiledFunction
->
nFormals
; ++
i
) {
125
ic
=
ic
->
addMember
(
engine
->
identifierTable
->
asPropertyKey
(
compilationUnit
->
runtimeStrings
[
formalsIndices
[
i
].
nameIndex
]),
Attr_NotConfigurable
);
126
if
(
enforceJsTypes
&& !
isSpecificType
(
formalsIndices
[
i
].
type
))
127
enforceJsTypes
=
false
;
128
}
129
internalClass
.
set
(
engine
,
ic
->
d
());
130
131
nFormals
=
compiledFunction
->
nFormals
;
132
133
if
(!
enforceJsTypes
)
134
return
;
135
136
if
(
aotFunction
) {
137
aotCompiledCode
=
aotFunction
->
functionPtr
;
138
new
(&
aotCompiledFunction
)
AOTCompiledFunction
;
139
kind
=
AotCompiled
;
140
aotCompiledFunction
.
types
.
resize
(
aotFunction
->
numArguments
+ 1);
141
aotFunction
->
signature
(
unit
,
aotCompiledFunction
.
types
.
data
());
142
return
;
143
}
144
145
// If a function has any typed arguments, but an untyped return value, the return value is void.
146
// If it doesn't have any arguments at all and the return value is untyped, the function is
147
// untyped. Users can specifically set the return type to "void" to have it enforced.
148
if
(
nFormals
== 0 && !
isSpecificType
(
compiledFunction
->
returnType
))
149
return
;
150
151
QQmlTypeLoader
*
typeLoader
=
engine
->
typeLoader
();
152
153
const
auto
isEnumUsedAsType
= [&](
const
QV4
::
ExecutableCompilationUnit
*
unit
,
154
int
elementNameId
,
QQmlTypeLoader
*
typeLoader
,
155
const
quint16
*
parameter
=
nullptr
) {
156
const
QStringView
name
=
unit
->
baseCompilationUnit
()->
stringAt
(
elementNameId
);
157
const
auto
split
=
name
.
tokenize
(u'.').
toContainer
<
QVarLengthArray
<
QStringView
, 4>>();
158
if
(
split
.
size
() != 2)
159
return
false
;
160
161
const
QStringView
scopeName
=
split
[0];
162
const
QStringView
enumName
=
split
[1];
163
164
auto
*
pengine
=
QQmlEnginePrivate
::
get
(
engine
);
165
const
auto
warn
= [&] {
166
QQmlError
error
;
167
auto
where
=
parameter
?
QStringLiteral
(
"parameter "
) +
QString
::
number
(*
parameter
)
168
:
QStringLiteral
(
"return type"
);
169
auto
msg
=
QStringLiteral
(
"Type annotation for %1 of function %2: Enumerations are "
170
"not types. Use underlying type (int or double) instead."
)
171
.
arg
(
where
,
this
->
name
()->
toQString
());
172
error
.
setDescription
(
msg
);
173
error
.
setUrl
(
QUrl
(
sourceFile
()));
174
error
.
setLine
(
this
->
sourceLocation
().
line
);
175
error
.
setColumn
(
this
->
sourceLocation
().
column
);
176
error
.
setMessageType
(
QtWarningMsg
);
177
pengine
->
warning
(
error
);
178
};
179
180
bool
ok
;
181
if
(
scopeName
==
QStringLiteral
(
"Qt"
)) {
182
const
QMetaObject
*
mo
= &
Qt
::
staticMetaObject
;
183
for
(
int
i
= 0;
i
<
mo
->
enumeratorCount
(); ++
i
) {
184
if
(
mo
->
enumerator
(
i
).
name
() ==
enumName
.
toLatin1
()) {
185
warn
();
186
return
true
;
187
}
188
}
189
return
false
;
190
}
191
192
const
QQmlType
scope
=
unit
->
typeNameCache
()->
query
<
QQmlImport
::
AllowRecursion
>(
193
scopeName
,
typeLoader
).
type
;
194
if
(!
scope
.
isValid
())
195
return
false
;
196
197
scope
.
scopedEnumIndex
(
typeLoader
,
enumName
.
toString
(), &
ok
);
198
if
(
ok
) {
199
warn
();
200
return
true
;
201
}
202
scope
.
unscopedEnumIndex
(
typeLoader
,
enumName
.
toString
(), &
ok
);
203
if
(
ok
) {
204
warn
();
205
return
true
;
206
}
207
208
return
false
;
209
};
210
211
auto
findQmlType
= [&](
const
CompiledData
::
ParameterType
&
param
,
212
const
quint16
*
parameter
=
nullptr
) {
213
const
quint32
type
=
param
.
typeNameIndexOrCommonType
();
214
if
(
param
.
indexIsCommonType
()) {
215
return
QQmlMetaType
::
qmlType
(
QQmlPropertyCacheCreatorBase
::
metaTypeForPropertyType
(
216
QV4
::
CompiledData
::
CommonType
(
type
)));
217
}
218
219
if
(
type
== 0 || !
typeLoader
)
220
return
QQmlType
();
221
222
if
(
isEnumUsedAsType
(
unit
,
type
,
typeLoader
,
parameter
))
223
return
QQmlType
();
224
225
const
QQmlType
qmltype
=
QQmlTypePrivate
::
visibleQmlTypeByName
(
unit
,
type
,
typeLoader
);
226
return
qmltype
.
typeId
().
isValid
() ?
qmltype
:
QQmlType
();
227
};
228
229
new
(&
jsTypedFunction
)
JSTypedFunction
;
230
kind
=
JsTyped
;
231
jsTypedFunction
.
types
.
reserve
(
nFormals
+ 1);
232
jsTypedFunction
.
types
.
append
(
findQmlType
(
compiledFunction
->
returnType
));
233
for
(
quint16
i
= 0;
i
<
nFormals
; ++
i
)
234
jsTypedFunction
.
types
.
append
(
findQmlType
(
formalsIndices
[
i
].
type
, &
i
));
235
}
236
237
Function
::~
Function
()
238
{
239
if
(
codeRef
) {
240
destroyFunctionTable
(
this
,
codeRef
);
241
delete
codeRef
;
242
}
243
244
switch
(
kind
) {
245
case
JsTyped
:
246
jsTypedFunction
.~
JSTypedFunction
();
247
break
;
248
case
AotCompiled
:
249
aotCompiledFunction
.~
AOTCompiledFunction
();
250
break
;
251
case
JsUntyped
:
252
case
Eval
:
253
break
;
254
}
255
}
256
257
void
Function
::
updateInternalClass
(
ExecutionEngine
*
engine
,
const
QList
<
QByteArray
> &
parameters
)
258
{
259
QStringList
parameterNames
;
260
261
// Resolve duplicate parameter names:
262
for
(
int
i
= 0,
ei
=
parameters
.
size
();
i
!=
ei
; ++
i
) {
263
const
QByteArray
&
param
=
parameters
.
at
(
i
);
264
int
duplicate
= -1;
265
266
for
(
int
j
=
i
- 1;
j
>= 0; --
j
) {
267
const
QByteArray
&
prevParam
=
parameters
.
at
(
j
);
268
if
(
param
==
prevParam
) {
269
duplicate
=
j
;
270
break
;
271
}
272
}
273
274
if
(
duplicate
== -1) {
275
parameterNames
.
append
(
QString
::
fromUtf8
(
param
));
276
}
else
{
277
const
QString
dup
=
parameterNames
[
duplicate
];
278
parameterNames
.
append
(
dup
);
279
parameterNames
[
duplicate
] =
280
QString
(
QChar
(0xfffe)) +
QString
::
number
(
duplicate
) +
dup
;
281
}
282
283
}
284
285
Scope
scope
(
engine
);
286
Scoped
<
InternalClass
>
ic
(
scope
,
engine
->
internalClasses
(
EngineBase
::
Class_CallContext
));
287
288
// first locals
289
const
quint32_le
*
localsIndices
=
compiledFunction
->
localsTable
();
290
for
(
quint32
i
= 0;
i
<
compiledFunction
->
nLocals
; ++
i
) {
291
ic
=
ic
->
addMember
(
292
engine
->
identifierTable
->
asPropertyKey
(
compilationUnit
->
runtimeStrings
[
localsIndices
[
i
]]),
293
Attr_NotConfigurable
);
294
}
295
296
ScopedString
arg
(
scope
);
297
for
(
const
QString
&
parameterName
:
parameterNames
) {
298
arg
=
engine
->
newIdentifier
(
parameterName
);
299
ic
=
ic
->
addMember
(
arg
->
propertyKey
(),
Attr_NotConfigurable
);
300
}
301
internalClass
.
set
(
engine
,
ic
->
d
());
302
nFormals
=
parameters
.
size
();
303
}
304
305
QString
Function
::
prettyName
(
const
Function
*
function
,
const
void
*
code
)
306
{
307
QString
prettyName
=
function
?
function
->
name
()->
toQString
() :
QString
();
308
if
(
prettyName
.
isEmpty
()) {
309
prettyName
=
QString
::
number
(
reinterpret_cast
<
quintptr
>(
code
), 16);
310
prettyName
.
prepend
(
QLatin1String
(
"QV4::Function(0x"
));
311
prettyName
.
append
(
QLatin1Char
(
')'
));
312
}
313
return
prettyName
;
314
}
315
316
QQmlSourceLocation
Function
::
sourceLocation
()
const
317
{
318
return
QQmlSourceLocation
(
319
sourceFile
(),
compiledFunction
->
location
.
line
(),
compiledFunction
->
location
.
column
());
320
}
321
322
FunctionData
::
FunctionData
(
EngineBase
*
engine
,
ExecutableCompilationUnit
*
compilationUnit_
)
323
{
324
compilationUnit
.
set
(
engine
,
compilationUnit_
);
325
}
326
327
}
// namespace QV4
328
329
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qrandomaccessasyncfile_darwin.mm:17
QV4
Definition
qjsvalue.h:24
QV4::doCall
static ReturnedValue doCall(QV4::Function *self, const QV4::Value *thisObject, const QV4::Value *argv, int argc, QV4::ExecutionContext *context)
Definition
qv4function.cpp:42
QV4::isSpecificType
static bool isSpecificType(const CompiledData::ParameterType &type)
Definition
qv4function.cpp:100
qtdeclarative
src
qml
jsruntime
qv4function.cpp
Generated on
for Qt by
1.16.1