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