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
qv4executablecompilationunit.cpp
Go to the documentation of this file.
1
// Copyright (C) 2019 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
"qml/qqmlprivate.h"
6
#
include
"qv4engine_p.h"
7
#
include
"qv4executablecompilationunit_p.h"
8
9
#
include
<
private
/
qv4engine_p
.
h
>
10
#
include
<
private
/
qv4regexp_p
.
h
>
11
#
include
<
private
/
qv4lookup_p
.
h
>
12
#
include
<
private
/
qv4qmlcontext_p
.
h
>
13
#
include
<
private
/
qv4identifiertable_p
.
h
>
14
#
include
<
private
/
qv4objectproto_p
.
h
>
15
#
include
<
private
/
qqmlengine_p
.
h
>
16
#
include
<
private
/
qv4qobjectwrapper_p
.
h
>
17
#
include
<
private
/
qqmlvaluetypewrapper_p
.
h
>
18
#
include
<
private
/
qqmlscriptdata_p
.
h
>
19
#
include
<
private
/
qv4module_p
.
h
>
20
#
include
<
private
/
qv4compilationunitmapper_p
.
h
>
21
#
include
<
private
/
qqmltypewrapper_p
.
h
>
22
#
include
<
private
/
qv4resolvedtypereference_p
.
h
>
23
#
include
<
private
/
qv4objectiterator_p
.
h
>
24
25
#
include
<
QtQml
/
qqmlpropertymap
.
h
>
26
27
#
include
<
QtCore
/
qfileinfo
.
h
>
28
#
include
<
QtCore
/
qcryptographichash
.
h
>
29
30
QT_BEGIN_NAMESPACE
31
32
DEFINE_BOOL_CONFIG_OPTION(qv4FailOnInvalidAot, QV4_FAIL_ON_INVALID_AOT)
33
DEFINE_BOOL_CONFIG_OPTION(qv4SkipAotValidation, QV4_SKIP_AOT_VALIDATION)
34
35
namespace
QV4
{
36
37
ExecutableCompilationUnit
::
ExecutableCompilationUnit
() =
default
;
38
39
ExecutableCompilationUnit
::
ExecutableCompilationUnit
(
40
QQmlRefPointer
<
CompiledData
::
CompilationUnit
> &&
compilationUnit
)
41
:
m_compilationUnit
(
std
::
move
(
compilationUnit
))
42
{
43
constants
=
m_compilationUnit
->
constants
;
44
}
45
46
ExecutableCompilationUnit
::~
ExecutableCompilationUnit
()
47
{
48
if
(
engine
)
49
clear
();
50
}
51
52
static
QString
toString
(QV4::ReturnedValue v)
53
{
54
Value val = Value::fromReturnedValue(v);
55
QString result;
56
if
(val.isInt32())
57
result = QLatin1String(
"int "
);
58
else
if
(val.isDouble())
59
result = QLatin1String(
"double "
);
60
if
(val.isEmpty())
61
result += QLatin1String(
"empty"
);
62
else
63
result += val.toQStringNoThrow();
64
return
result;
65
}
66
67
static
void
dumpConstantTable
(
const
StaticValue *constants, uint count)
68
{
69
QDebug d = qDebug();
70
d.nospace() << Qt::right;
71
for
(uint i = 0; i < count; ++i) {
72
d << qSetFieldWidth(8) << i << qSetFieldWidth(0) <<
": "
73
<< toString(constants[i].asReturnedValue()).toUtf8().constData() <<
"\n"
;
74
}
75
}
76
77
void
ExecutableCompilationUnit
::
populate
()
78
{
79
/* In general, we should use QV4::Scope whenever we allocate heap objects, and employ write barriers
80
for member variables pointing to heap objects. However, ExecutableCompilationUnit is special, as it
81
is always part of the root set. So instead of using scoped allocations and write barriers, we use a
82
slightly different approach: We temporarily block the gc from running. Afterwards, at the end of the
83
function we check whether the gc was already running, and mark the ExecutableCompilationUnit. This
84
ensures that all the newly allocated objects of the compilation unit will be marked in turn.
85
If the gc was not running, we don't have to do anything, because everything will be marked when the
86
gc starts marking the root set at the start of a run.
87
*/
88
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
89
GCCriticalSection
<
ExecutableCompilationUnit
>
criticalSection
(
engine
,
this
);
90
91
Q_ASSERT
(!
runtimeStrings
);
92
Q_ASSERT
(
engine
);
93
Q_ASSERT
(
data
);
94
const
quint32
stringCount
=
totalStringCount
();
95
runtimeStrings
= (
QV4
::
Heap
::
String
**)
calloc
(
stringCount
,
sizeof
(
QV4
::
Heap
::
String
*));
96
for
(
uint
i
= 0;
i
<
stringCount
; ++
i
)
97
runtimeStrings
[
i
] =
engine
->
newString
(
stringAt
(
i
));
98
99
runtimeRegularExpressions
100
=
new
QV4
::
Value
[
data
->
regexpTableSize
];
101
for
(
uint
i
= 0;
i
<
data
->
regexpTableSize
; ++
i
) {
102
const
CompiledData
::
RegExp
*
re
=
data
->
regexpAt
(
i
);
103
uint
f
=
re
->
flags
();
104
const
CompiledData
::
RegExp
::
Flags
flags
=
static_cast
<
CompiledData
::
RegExp
::
Flags
>(
f
);
105
runtimeRegularExpressions
[
i
] =
QV4
::
RegExp
::
create
(
106
engine
,
stringAt
(
re
->
stringIndex
()),
flags
);
107
}
108
109
if
(
data
->
lookupTableSize
) {
110
runtimeLookups
=
new
QV4
::
Lookup
[
data
->
lookupTableSize
];
111
memset
(
runtimeLookups
, 0,
data
->
lookupTableSize
*
sizeof
(
QV4
::
Lookup
));
112
const
CompiledData
::
Lookup
*
compiledLookups
=
data
->
lookupTable
();
113
for
(
uint
i
= 0;
i
<
data
->
lookupTableSize
; ++
i
) {
114
QV4
::
Lookup
*
l
=
runtimeLookups
+
i
;
115
116
CompiledData
::
Lookup
::
Type
type
117
=
CompiledData
::
Lookup
::
Type
(
uint
(
compiledLookups
[
i
].
type
()));
118
if
(
type
==
CompiledData
::
Lookup
::
Type_Getter
)
119
l
->
call
=
Lookup
::
Call
::
GetterGeneric
;
120
else
if
(
type
==
CompiledData
::
Lookup
::
Type_Setter
)
121
l
->
call
=
Lookup
::
Call
::
SetterGeneric
;
122
else
if
(
type
==
CompiledData
::
Lookup
::
Type_GlobalGetter
)
123
l
->
call
=
Lookup
::
Call
::
GlobalGetterGeneric
;
124
else
if
(
type
==
CompiledData
::
Lookup
::
Type_QmlContextPropertyGetter
)
125
l
->
call
=
Lookup
::
Call
::
ContextGetterGeneric
;
126
l
->
forCall
=
compiledLookups
[
i
].
mode
() ==
CompiledData
::
Lookup
::
Mode_ForCall
;
127
l
->
nameIndex
=
compiledLookups
[
i
].
nameIndex
();
128
}
129
}
130
131
if
(
data
->
jsClassTableSize
) {
132
runtimeClasses
133
= (
QV4
::
Heap
::
InternalClass
**)
calloc
(
data
->
jsClassTableSize
,
134
sizeof
(
QV4
::
Heap
::
InternalClass
*));
135
136
for
(
uint
i
= 0;
i
<
data
->
jsClassTableSize
; ++
i
) {
137
int
memberCount
= 0;
138
const
CompiledData
::
JSClassMember
*
member
139
=
data
->
jsClassAt
(
i
, &
memberCount
);
140
runtimeClasses
[
i
]
141
=
engine
->
internalClasses
(
QV4
::
ExecutionEngine
::
Class_Object
);
142
for
(
int
j
= 0;
j
<
memberCount
; ++
j
, ++
member
)
143
runtimeClasses
[
i
]
144
=
runtimeClasses
[
i
]->
addMember
(
145
engine
->
identifierTable
->
asPropertyKey
(
146
runtimeStrings
[
member
->
nameOffset
()]),
147
member
->
isAccessor
()
148
?
QV4
::
Attr_Accessor
149
:
QV4
::
Attr_Data
);
150
}
151
}
152
153
const
auto
validateCULookupSignatures
= [&]() ->
bool
{
154
if
(
qv4SkipAotValidation
())
155
return
true
;
156
if
(!
m_compilationUnit
->
aotCompiledFunctions
)
157
return
true
;
// Non-existent code can't be invalid
158
159
Q_ASSERT
(
data
->
version
>= 0x4d);
// Otherwise validateLookupSignatures is uninitialized
160
const
CompiledData
::
LookupValidationFn
v
=
m_compilationUnit
->
validateLookupSignatures
;
161
bool
valid
=
v
&&
v
(
engine
->
qmlEngine
(),
m_compilationUnit
.
data
());
162
163
if
(!
valid
&&
qv4FailOnInvalidAot
()) {
164
// The compile time and run time AOT lookup signatures don't match. A rebuild is needed.
165
qFatal
(
"AOT lookup signatures validation failed for file %s. A rebuild is needed. %s"
,
166
fileName
().
toUtf8
().
constData
(),
"[QV4_FAIL_ON_INVALID_AOT]"
);
167
}
168
return
valid
;
169
};
170
171
runtimeFunctions
.
resize
(
data
->
functionTableSize
);
172
static
const
bool
staticIgnoreAotCompiledFunctions
173
=
qEnvironmentVariableIsSet
(
"QV4_FORCE_INTERPRETER"
)
174
|| !(
engine
->
diskCacheOptions
() &
ExecutionEngine
::
DiskCache
::
AotNative
);
175
176
bool
ignoreAotCompiledFunctions
=
staticIgnoreAotCompiledFunctions
177
|| !
validateCULookupSignatures
();
178
179
const
QQmlPrivate
::
AOTCompiledFunction
*
aotFunction
180
=
ignoreAotCompiledFunctions
?
nullptr
:
m_compilationUnit
->
aotCompiledFunctions
;
181
182
auto
advanceAotFunction
= [&](
int
i
) ->
const
QQmlPrivate
::
AOTCompiledFunction
* {
183
if
(
aotFunction
) {
184
if
(
aotFunction
->
functionPtr
) {
185
if
(
aotFunction
->
functionIndex
==
i
)
186
return
aotFunction
++;
187
}
else
{
188
aotFunction
=
nullptr
;
189
}
190
}
191
return
nullptr
;
192
};
193
194
for
(
int
i
= 0 ;
i
<
runtimeFunctions
.
size
(); ++
i
) {
195
const
QV4
::
CompiledData
::
Function
*
compiledFunction
=
data
->
functionAt
(
i
);
196
runtimeFunctions
[
i
] =
QV4
::
Function
::
create
(
engine
,
this
,
compiledFunction
,
197
advanceAotFunction
(
i
));
198
}
199
200
Scope
scope
(
engine
);
201
Scoped
<
InternalClass
>
ic
(
scope
);
202
203
runtimeBlocks
.
resize
(
data
->
blockTableSize
);
204
for
(
int
i
= 0 ;
i
<
runtimeBlocks
.
size
(); ++
i
) {
205
const
QV4
::
CompiledData
::
Block
*
compiledBlock
=
data
->
blockAt
(
i
);
206
ic
=
engine
->
internalClasses
(
EngineBase
::
Class_CallContext
);
207
208
// first locals
209
const
quint32_le
*
localsIndices
=
compiledBlock
->
localsTable
();
210
for
(
quint32
j
= 0;
j
<
compiledBlock
->
nLocals
; ++
j
)
211
ic
=
ic
->
addMember
(
212
engine
->
identifierTable
->
asPropertyKey
(
runtimeStrings
[
localsIndices
[
j
]]),
213
Attr_NotConfigurable
);
214
runtimeBlocks
[
i
] =
ic
->
d
();
215
}
216
217
static
const
bool
showCode
=
qEnvironmentVariableIsSet
(
"QV4_SHOW_BYTECODE"
);
218
if
(
showCode
) {
219
qDebug
() <<
"=== Constant table"
;
220
dumpConstantTable
(
constants
,
data
->
constantTableSize
);
221
qDebug
() <<
"=== String table"
;
222
for
(
uint
i
= 0,
end
=
totalStringCount
();
i
<
end
; ++
i
)
223
qDebug
() <<
" "
<<
i
<<
":"
<<
runtimeStrings
[
i
]->
toQString
();
224
qDebug
() <<
"=== Closure table"
;
225
for
(
uint
i
= 0;
i
<
data
->
functionTableSize
; ++
i
)
226
qDebug
() <<
" "
<<
i
<<
":"
<<
runtimeFunctions
[
i
]->
name
()->
toQString
();
227
qDebug
() <<
"root function at index "
228
<< (
data
->
indexOfRootFunction
!= -1
229
?
data
->
indexOfRootFunction
: 0);
230
}
231
}
232
233
Heap
::
Object
*
ExecutableCompilationUnit
::
templateObjectAt
(
int
index
)
const
234
{
235
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
236
Q_ASSERT
(
data
);
237
Q_ASSERT
(
engine
);
238
239
Q_ASSERT
(
index
<
int
(
data
->
templateObjectTableSize
));
240
if
(!
templateObjects
.
size
())
241
templateObjects
.
resize
(
data
->
templateObjectTableSize
);
242
Heap
::
Object
*
o
=
templateObjects
.
at
(
index
);
243
if
(
o
)
244
return
o
;
245
246
// create the template object
247
Scope
scope
(
engine
);
248
const
CompiledData
::
TemplateObject
*
t
=
data
->
templateObjectAt
(
index
);
249
Scoped
<
ArrayObject
>
a
(
scope
,
engine
->
newArrayObject
(
t
->
size
));
250
Scoped
<
ArrayObject
>
raw
(
scope
,
engine
->
newArrayObject
(
t
->
size
));
251
ScopedValue
s
(
scope
);
252
for
(
uint
i
= 0;
i
<
t
->
size
; ++
i
) {
253
s
=
runtimeStrings
[
t
->
stringIndexAt
(
i
)];
254
a
->
arraySet
(
i
,
s
);
255
s
=
runtimeStrings
[
t
->
rawStringIndexAt
(
i
)];
256
raw
->
arraySet
(
i
,
s
);
257
}
258
259
ObjectPrototype
::
method_freeze
(
engine
->
functionCtor
(),
nullptr
,
raw
, 1);
260
a
->
defineReadonlyProperty
(
QStringLiteral
(
"raw"
),
raw
);
261
ObjectPrototype
::
method_freeze
(
engine
->
functionCtor
(),
nullptr
,
a
, 1);
262
263
templateObjects
[
index
] =
a
->
objectValue
()->
d
();
264
return
templateObjects
.
at
(
index
);
265
}
266
267
void
ExecutableCompilationUnit
::
clear
()
268
{
269
delete
[]
imports
;
270
imports
=
nullptr
;
271
272
if
(
runtimeLookups
) {
273
const
uint
lookupTableSize
=
unitData
()->
lookupTableSize
;
274
for
(
uint
i
= 0;
i
<
lookupTableSize
; ++
i
)
275
runtimeLookups
[
i
].
releasePropertyCache
();
276
}
277
278
delete
[]
runtimeLookups
;
279
runtimeLookups
=
nullptr
;
280
281
for
(
QV4
::
Function
*
f
:
std
::
as_const
(
runtimeFunctions
))
282
f
->
destroy
();
283
runtimeFunctions
.
clear
();
284
285
free
(
runtimeStrings
);
286
runtimeStrings
=
nullptr
;
287
delete
[]
runtimeRegularExpressions
;
288
runtimeRegularExpressions
=
nullptr
;
289
free
(
runtimeClasses
);
290
runtimeClasses
=
nullptr
;
291
292
static
QQmlRefPointer
<
CompiledData
::
CompilationUnit
>
nullUnit
293
=
QQml
::
makeRefPointer
<
CompiledData
::
CompilationUnit
>();
294
m_compilationUnit
=
nullUnit
;
295
}
296
297
void
ExecutableCompilationUnit
::
markObjects
(
QV4
::
MarkStack
*
markStack
)
const
298
{
299
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
300
301
if
(
runtimeStrings
) {
302
for
(
uint
i
= 0,
end
=
totalStringCount
();
i
<
end
; ++
i
)
303
if
(
runtimeStrings
[
i
])
304
runtimeStrings
[
i
]->
mark
(
markStack
);
305
}
306
if
(
runtimeRegularExpressions
) {
307
for
(
uint
i
= 0;
i
<
data
->
regexpTableSize
; ++
i
)
308
Value
::
fromStaticValue
(
runtimeRegularExpressions
[
i
]).
mark
(
markStack
);
309
}
310
if
(
runtimeClasses
) {
311
for
(
uint
i
= 0;
i
<
data
->
jsClassTableSize
; ++
i
)
312
if
(
runtimeClasses
[
i
])
313
runtimeClasses
[
i
]->
mark
(
markStack
);
314
}
315
for
(
QV4
::
Function
*
f
:
std
::
as_const
(
runtimeFunctions
))
316
if
(
f
&&
f
->
internalClass
)
317
f
->
internalClass
->
mark
(
markStack
);
318
for
(
QV4
::
Heap
::
InternalClass
*
c
:
std
::
as_const
(
runtimeBlocks
))
319
if
(
c
)
320
c
->
mark
(
markStack
);
321
322
for
(
QV4
::
Heap
::
Object
*
o
:
std
::
as_const
(
templateObjects
))
323
if
(
o
)
324
o
->
mark
(
markStack
);
325
326
if
(
runtimeLookups
) {
327
for
(
uint
i
= 0;
i
<
data
->
lookupTableSize
; ++
i
)
328
runtimeLookups
[
i
].
markObjects
(
markStack
);
329
}
330
331
if
(
Heap
::
Base
*
v
=
m_valueOrModule
.
heapObject
())
332
v
->
mark
(
markStack
);
333
}
334
335
IdentifierHash
ExecutableCompilationUnit
::
createNamedObjectsPerComponent
(
int
componentObjectIndex
)
336
{
337
IdentifierHash
namedObjectCache
(
engine
);
338
const
CompiledData
::
Object
*
component
=
objectAt
(
componentObjectIndex
);
339
const
quint32_le
*
namedObjectIndexPtr
=
component
->
namedObjectsInComponentTable
();
340
for
(
quint32
i
= 0;
i
<
component
->
nNamedObjectsInComponent
; ++
i
, ++
namedObjectIndexPtr
) {
341
const
CompiledData
::
Object
*
namedObject
=
objectAt
(*
namedObjectIndexPtr
);
342
namedObjectCache
.
add
(
runtimeStrings
[
namedObject
->
idNameIndex
],
namedObject
->
objectId
());
343
}
344
Q_ASSERT
(
namedObjectCache
.
isValid
());
345
return
*
namedObjectsPerComponentCache
.
insert
(
componentObjectIndex
,
namedObjectCache
);
346
}
347
348
QQmlRefPointer
<
ExecutableCompilationUnit
>
ExecutableCompilationUnit
::
create
(
349
QQmlRefPointer
<
CompiledData
::
CompilationUnit
> &&
compilationUnit
,
ExecutionEngine
*
engine
)
350
{
351
auto
result
=
QQmlRefPointer
<
ExecutableCompilationUnit
>(
352
new
ExecutableCompilationUnit
(
std
::
move
(
compilationUnit
)),
353
QQmlRefPointer
<
ExecutableCompilationUnit
>::
Adopt
);
354
result
->
engine
=
engine
;
355
return
result
;
356
}
357
358
Heap
::
Module
*
ExecutableCompilationUnit
::
instantiate
()
359
{
360
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
361
362
if
(
isESModule
() &&
module
())
363
return
module
();
364
365
if
(
data
->
indexOfRootFunction
< 0)
366
return
nullptr
;
367
368
Q_ASSERT
(
engine
);
369
if
(!
runtimeStrings
)
370
populate
();
371
372
Scope
scope
(
engine
);
373
Scoped
<
Module
>
module
(
scope
,
engine
->
memoryManager
->
allocate
<
Module
>(
engine
,
this
));
374
375
if
(
isESModule
())
376
setModule
(
module
->
d
());
377
378
for
(
uint
i
= 0,
end
=
data
->
moduleRequestTableSize
;
i
<
end
; ++
i
) {
379
const
auto
dependentModuleUnit
=
dependentModule
(
urlAt
(
data
->
moduleRequestTable
()[
i
]));
380
if
(
engine
->
hasException
)
381
return
nullptr
;
382
if
(
dependentModuleUnit
)
383
dependentModuleUnit
->
instantiate
();
384
}
385
386
ScopedString
importName
(
scope
);
387
388
const
uint
importCount
=
data
->
importEntryTableSize
;
389
if
(
importCount
> 0) {
390
imports
=
new
const
StaticValue
*[
importCount
];
391
memset
(
imports
, 0,
importCount
*
sizeof
(
StaticValue
*));
392
}
393
for
(
uint
i
= 0;
i
<
importCount
; ++
i
) {
394
const
CompiledData
::
ImportEntry
&
entry
=
data
->
importEntryTable
()[
i
];
395
importName
=
runtimeStrings
[
entry
.
importName
];
396
397
if
(
const
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
398
const
Value
*
valuePtr
=
module
->
resolveExport
(
importName
);
399
if
(!
valuePtr
) {
400
QString
referenceErrorMessage
=
QStringLiteral
(
"Unable to resolve import reference "
);
401
referenceErrorMessage
+=
importName
->
toQString
();
402
QV4
::
ScopedValue
compiledValue
(
scope
,
module
->
value
());
403
engine
->
throwReferenceError
(
404
referenceErrorMessage
,
fileName
(),
405
entry
.
location
.
line
(),
entry
.
location
.
column
());
406
return
nullptr
;
407
}
408
imports
[
i
] =
valuePtr
;
409
}
410
}
411
412
const
auto
throwReferenceError
= [&](
const
CompiledData
::
ExportEntry
&
entry
,
const
QString
&
importName
) {
413
QString
referenceErrorMessage
=
QStringLiteral
(
"Unable to resolve re-export reference "
);
414
referenceErrorMessage
+=
importName
;
415
engine
->
throwReferenceError
(
416
referenceErrorMessage
,
fileName
(),
417
entry
.
location
.
line
(),
entry
.
location
.
column
());
418
};
419
420
for
(
uint
i
= 0;
i
<
data
->
indirectExportEntryTableSize
; ++
i
) {
421
const
CompiledData
::
ExportEntry
&
entry
=
data
->
indirectExportEntryTable
()[
i
];
422
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
423
ScopedString
importName
(
scope
,
runtimeStrings
[
entry
.
importName
]);
424
if
(!
module
->
resolveExport
(
importName
)) {
425
throwReferenceError
(
entry
,
importName
->
toQString
());
426
return
nullptr
;
427
}
428
}
429
}
430
431
return
module
->
d
();
432
}
433
434
const
Value
*
ExecutableCompilationUnit
::
resolveExportRecursively
(
435
QV4
::
String
*
exportName
,
QList
<
ResolveSetEntry
> *
resolveSet
)
const
436
{
437
if
(!
module
())
438
return
nullptr
;
439
440
for
(
const
auto
&
entry
:
std
::
as_const
(*
resolveSet
)) {
441
if
(
entry
.
module
==
this
&&
entry
.
exportName
->
isEqualTo
(
exportName
))
442
return
nullptr
;
443
}
444
445
(*
resolveSet
) <<
ResolveSetEntry
(
this
,
exportName
);
446
447
if
(
exportName
->
toQString
() ==
QLatin1String
(
"*"
))
448
return
&
module
()->
self
;
449
450
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
451
452
Q_ASSERT
(
data
);
453
Q_ASSERT
(
engine
);
454
455
Scope
scope
(
engine
);
456
457
if
(
auto
localExport
=
lookupNameInExportTable
(
458
data
->
localExportEntryTable
(),
data
->
localExportEntryTableSize
,
exportName
)) {
459
ScopedString
localName
(
scope
,
runtimeStrings
[
localExport
->
localName
]);
460
uint
index
=
module
()->
scope
->
internalClass
->
indexOfValueOrGetter
(
localName
->
toPropertyKey
());
461
if
(
index
==
UINT_MAX
)
462
return
nullptr
;
463
if
(
index
>=
module
()->
scope
->
locals
.
size
)
464
return
&(
imports
[
index
-
module
()->
scope
->
locals
.
size
]->
asValue
<
Value
>());
465
return
&
module
()->
scope
->
locals
[
index
];
466
}
467
468
if
(
auto
indirectExport
=
lookupNameInExportTable
(
469
data
->
indirectExportEntryTable
(),
data
->
indirectExportEntryTableSize
,
exportName
)) {
470
if
(
auto
module
=
dependentModule
(
urlAt
(
indirectExport
->
moduleRequest
))) {
471
ScopedString
importName
(
scope
,
runtimeStrings
[
indirectExport
->
importName
]);
472
return
module
->
resolveExportRecursively
(
importName
,
resolveSet
);
473
}
474
return
nullptr
;
475
}
476
477
if
(
exportName
->
toQString
() ==
QLatin1String
(
"default"
))
478
return
nullptr
;
479
480
const
Value
*
starResolution
=
nullptr
;
481
482
for
(
uint
i
= 0;
i
<
data
->
starExportEntryTableSize
; ++
i
) {
483
const
CompiledData
::
ExportEntry
&
entry
=
data
->
starExportEntryTable
()[
i
];
484
const
Value
*
resolution
=
nullptr
;
485
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
)))
486
resolution
=
module
->
resolveExportRecursively
(
exportName
,
resolveSet
);
487
488
// ### handle ambiguous
489
if
(
resolution
) {
490
if
(!
starResolution
) {
491
starResolution
=
resolution
;
492
continue
;
493
}
494
if
(
resolution
!=
starResolution
)
495
return
nullptr
;
496
}
497
}
498
499
return
starResolution
;
500
}
501
502
const
CompiledData
::
ExportEntry
*
ExecutableCompilationUnit
::
lookupNameInExportTable
(
503
const
CompiledData
::
ExportEntry
*
firstExportEntry
,
int
tableSize
,
QV4
::
String
*
name
)
const
504
{
505
const
CompiledData
::
ExportEntry
*
lastExportEntry
=
firstExportEntry
+
tableSize
;
506
auto
matchingExport
=
std
::
lower_bound
(
firstExportEntry
,
lastExportEntry
,
name
, [
this
](
const
CompiledData
::
ExportEntry
&
lhs
,
QV4
::
String
*
name
) {
507
return
stringAt
(
lhs
.
exportName
) <
name
->
toQString
();
508
});
509
if
(
matchingExport
==
lastExportEntry
||
stringAt
(
matchingExport
->
exportName
) !=
name
->
toQString
())
510
return
nullptr
;
511
return
matchingExport
;
512
}
513
514
void
ExecutableCompilationUnit
::
getExportedNamesRecursively
(
515
QStringList
*
names
,
QList
<
const
ExecutableCompilationUnit
*> *
exportNameSet
,
516
bool
includeDefaultExport
)
const
517
{
518
if
(
exportNameSet
->
contains
(
this
))
519
return
;
520
exportNameSet
->
append
(
this
);
521
522
const
auto
append
= [
names
,
includeDefaultExport
](
const
QString
&
name
) {
523
if
(!
includeDefaultExport
&&
name
==
QLatin1String
(
"default"
))
524
return
;
525
names
->
append
(
name
);
526
};
527
528
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
529
530
Q_ASSERT
(
data
);
531
Q_ASSERT
(
engine
);
532
533
for
(
uint
i
= 0;
i
<
data
->
localExportEntryTableSize
; ++
i
) {
534
const
CompiledData
::
ExportEntry
&
entry
=
data
->
localExportEntryTable
()[
i
];
535
append
(
stringAt
(
entry
.
exportName
));
536
}
537
538
for
(
uint
i
= 0;
i
<
data
->
indirectExportEntryTableSize
; ++
i
) {
539
const
CompiledData
::
ExportEntry
&
entry
=
data
->
indirectExportEntryTable
()[
i
];
540
append
(
stringAt
(
entry
.
exportName
));
541
}
542
543
for
(
uint
i
= 0;
i
<
data
->
starExportEntryTableSize
; ++
i
) {
544
const
CompiledData
::
ExportEntry
&
entry
=
data
->
starExportEntryTable
()[
i
];
545
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
546
module
->
getExportedNamesRecursively
(
547
names
,
exportNameSet
,
/*includeDefaultExport*/
false
);
548
}
549
}
550
}
551
552
void
ExecutableCompilationUnit
::
evaluate
()
553
{
554
Q_ASSERT
(
engine
);
555
556
QV4
::
Scope
scope
(
engine
);
557
QV4
::
Scoped
<
Module
>
mod
(
scope
,
module
());
558
mod
->
evaluate
();
559
}
560
561
void
ExecutableCompilationUnit
::
evaluateModuleRequests
()
562
{
563
Q_ASSERT
(
engine
);
564
565
const
CompiledData
::
Unit
*
data
=
unitData
();
566
for
(
uint
i
= 0,
end
=
data
->
moduleRequestTableSize
;
i
<
end
; ++
i
) {
567
auto
module
=
dependentModule
(
urlAt
(
data
->
moduleRequestTable
()[
i
]));
568
569
if
(
engine
->
hasException
)
570
return
;
571
572
Q_ASSERT
(
module
);
573
module
->
evaluate
();
574
if
(
engine
->
hasException
)
575
return
;
576
}
577
}
578
579
QString
ExecutableCompilationUnit
::
bindingValueAsString
(
const
CompiledData
::
Binding
*
binding
)
const
580
{
581
#
if
QT_CONFIG
(
translation
)
582
using
namespace
CompiledData
;
583
bool
byId
=
false
;
584
switch
(
binding
->
type
()) {
585
case
Binding
::
Type_TranslationById
:
586
byId
=
true
;
587
Q_FALLTHROUGH
();
588
case
Binding
::
Type_Translation
: {
589
return
translateFrom
({
binding
->
value
.
translationDataIndex
,
byId
});
590
}
591
default
:
592
break
;
593
}
594
#
endif
595
return
m_compilationUnit
->
bindingValueAsString
(
binding
);
596
}
597
598
QString
ExecutableCompilationUnit
::
translateFrom
(
TranslationDataIndex
index
)
const
599
{
600
#
if
!
QT_CONFIG
(
translation
)
601
return
QString
();
602
#
else
603
const
CompiledData
::
TranslationData
&
translation
=
unitData
()->
translations
()[
index
.
index
];
604
605
if
(
index
.
byId
) {
606
QByteArray
id
=
stringAt
(
translation
.
stringIndex
).
toUtf8
();
607
return
qtTrId
(
id
.
constData
(),
translation
.
number
);
608
}
609
610
const
auto
fileContext
= [
this
]() {
611
// This code must match that in the qsTr() implementation
612
const
QString
&
path
=
fileName
();
613
int
lastSlash
=
path
.
lastIndexOf
(
QLatin1Char
(
'/'
));
614
615
QStringView
context
= (
lastSlash
> -1)
616
?
QStringView
{
path
}.
mid
(
lastSlash
+ 1,
path
.
size
() -
lastSlash
- 5)
617
:
QStringView
();
618
return
context
.
toUtf8
();
619
};
620
621
const
bool
hasContext
622
=
translation
.
contextIndex
!=
QV4
::
CompiledData
::
TranslationData
::
NoContextIndex
;
623
QByteArray
context
;
624
if
(
hasContext
) {
625
context
=
stringAt
(
translation
.
contextIndex
).
toUtf8
();
626
}
else
{
627
auto
pragmaTranslationContext
=
unitData
()->
translationContextIndex
();
628
context
=
stringAt
(*
pragmaTranslationContext
).
toUtf8
();
629
context
=
context
.
isEmpty
() ?
fileContext
() :
context
;
630
}
631
632
QByteArray
comment
=
stringAt
(
translation
.
commentIndex
).
toUtf8
();
633
QByteArray
text
=
stringAt
(
translation
.
stringIndex
).
toUtf8
();
634
return
QCoreApplication
::
translate
(
context
,
text
,
comment
,
translation
.
number
);
635
#
endif
636
}
637
638
Heap
::
Module
*
ExecutableCompilationUnit
::
module
()
const
639
{
640
if
(
const
Module
*
m
=
m_valueOrModule
.
as
<
QV4
::
Module
>())
641
return
m
->
d
();
642
return
nullptr
;
643
}
644
645
void
ExecutableCompilationUnit
::
setModule
(
Heap
::
Module
*
module
)
646
{
647
// We don't necessarily hold any other references to ES modules. So, if the GC
648
// is running right now, we need to mark it. Otherwise it might collect it even
649
// though it's still reachable via the engine's list of compilation units.
650
QV4
::
WriteBarrier
::
markCustom
(
engine
, [
module
](
QV4
::
MarkStack
*
stack
) {
651
if
constexpr
(
QV4
::
WriteBarrier
::
isInsertionBarrier
) {
652
module
->
mark
(
stack
);
653
}
654
});
655
m_valueOrModule
=
module
;
656
}
657
658
}
// namespace QV4
659
660
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QV4
Definition
qjsvalue.h:24
QV4::dumpConstantTable
static void dumpConstantTable(const StaticValue *constants, uint count)
Definition
qv4executablecompilationunit.cpp:67
QV4::toString
static QString toString(QV4::ReturnedValue v)
Definition
qv4executablecompilationunit.cpp:52
qtdeclarative
src
qml
jsruntime
qv4executablecompilationunit.cpp
Generated on
for Qt by
1.16.1