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
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
::
RuntimeObject
*
component
339
=
m_compilationUnit
->
runtimeObjectAt
(
componentObjectIndex
);
340
const
quint32_le
*
namedObjectIndexPtr
=
component
->
namedObjectsInComponentTable
();
341
for
(
quint32
i
= 0;
i
<
component
->
nNamedObjectsInComponent
; ++
i
, ++
namedObjectIndexPtr
) {
342
namedObjectCache
.
add
(
runtimeStrings
[
objectAt
(*
namedObjectIndexPtr
)->
idNameIndex
],
343
m_compilationUnit
->
objectId
(*
namedObjectIndexPtr
));
344
}
345
Q_ASSERT
(
namedObjectCache
.
isValid
());
346
return
*
namedObjectsPerComponentCache
.
insert
(
componentObjectIndex
,
namedObjectCache
);
347
}
348
349
QQmlRefPointer
<
ExecutableCompilationUnit
>
ExecutableCompilationUnit
::
create
(
350
QQmlRefPointer
<
CompiledData
::
CompilationUnit
> &&
compilationUnit
,
ExecutionEngine
*
engine
)
351
{
352
auto
result
=
QQmlRefPointer
<
ExecutableCompilationUnit
>(
353
new
ExecutableCompilationUnit
(
std
::
move
(
compilationUnit
)),
354
QQmlRefPointer
<
ExecutableCompilationUnit
>::
Adopt
);
355
result
->
engine
=
engine
;
356
return
result
;
357
}
358
359
Heap
::
Module
*
ExecutableCompilationUnit
::
instantiate
()
360
{
361
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
362
363
if
(
isESModule
() &&
module
())
364
return
module
();
365
366
if
(
data
->
indexOfRootFunction
< 0)
367
return
nullptr
;
368
369
Q_ASSERT
(
engine
);
370
if
(!
runtimeStrings
)
371
populate
();
372
373
Scope
scope
(
engine
);
374
Scoped
<
Module
>
module
(
scope
,
engine
->
memoryManager
->
allocate
<
Module
>(
engine
,
this
));
375
376
if
(
isESModule
())
377
setModule
(
module
->
d
());
378
379
for
(
uint
i
= 0,
end
=
data
->
moduleRequestTableSize
;
i
<
end
; ++
i
) {
380
const
auto
dependentModuleUnit
=
dependentModule
(
urlAt
(
data
->
moduleRequestTable
()[
i
]));
381
if
(
engine
->
hasException
)
382
return
nullptr
;
383
if
(
dependentModuleUnit
)
384
dependentModuleUnit
->
instantiate
();
385
}
386
387
ScopedString
importName
(
scope
);
388
389
const
uint
importCount
=
data
->
importEntryTableSize
;
390
if
(
importCount
> 0) {
391
imports
=
new
const
StaticValue
*[
importCount
];
392
memset
(
imports
, 0,
importCount
*
sizeof
(
StaticValue
*));
393
}
394
for
(
uint
i
= 0;
i
<
importCount
; ++
i
) {
395
const
CompiledData
::
ImportEntry
&
entry
=
data
->
importEntryTable
()[
i
];
396
importName
=
runtimeStrings
[
entry
.
importName
];
397
398
if
(
const
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
399
const
Value
*
valuePtr
=
module
->
resolveExport
(
importName
);
400
if
(!
valuePtr
) {
401
QString
referenceErrorMessage
=
QStringLiteral
(
"Unable to resolve import reference "
);
402
referenceErrorMessage
+=
importName
->
toQString
();
403
QV4
::
ScopedValue
compiledValue
(
scope
,
module
->
value
());
404
engine
->
throwReferenceError
(
405
referenceErrorMessage
,
fileName
(),
406
entry
.
location
.
line
(),
entry
.
location
.
column
());
407
return
nullptr
;
408
}
409
imports
[
i
] =
valuePtr
;
410
}
411
}
412
413
const
auto
throwReferenceError
= [&](
const
CompiledData
::
ExportEntry
&
entry
,
const
QString
&
importName
) {
414
QString
referenceErrorMessage
=
QStringLiteral
(
"Unable to resolve re-export reference "
);
415
referenceErrorMessage
+=
importName
;
416
engine
->
throwReferenceError
(
417
referenceErrorMessage
,
fileName
(),
418
entry
.
location
.
line
(),
entry
.
location
.
column
());
419
};
420
421
for
(
uint
i
= 0;
i
<
data
->
indirectExportEntryTableSize
; ++
i
) {
422
const
CompiledData
::
ExportEntry
&
entry
=
data
->
indirectExportEntryTable
()[
i
];
423
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
424
ScopedString
importName
(
scope
,
runtimeStrings
[
entry
.
importName
]);
425
if
(!
module
->
resolveExport
(
importName
)) {
426
throwReferenceError
(
entry
,
importName
->
toQString
());
427
return
nullptr
;
428
}
429
}
430
}
431
432
return
module
->
d
();
433
}
434
435
const
Value
*
ExecutableCompilationUnit
::
resolveExportRecursively
(
436
QV4
::
String
*
exportName
,
QList
<
ResolveSetEntry
> *
resolveSet
)
const
437
{
438
if
(!
module
())
439
return
nullptr
;
440
441
for
(
const
auto
&
entry
:
std
::
as_const
(*
resolveSet
)) {
442
if
(
entry
.
module
==
this
&&
entry
.
exportName
->
isEqualTo
(
exportName
))
443
return
nullptr
;
444
}
445
446
(*
resolveSet
) <<
ResolveSetEntry
(
this
,
exportName
);
447
448
if
(
exportName
->
toQString
() ==
QLatin1String
(
"*"
))
449
return
&
module
()->
self
;
450
451
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
452
453
Q_ASSERT
(
data
);
454
Q_ASSERT
(
engine
);
455
456
Scope
scope
(
engine
);
457
458
if
(
auto
localExport
=
lookupNameInExportTable
(
459
data
->
localExportEntryTable
(),
data
->
localExportEntryTableSize
,
exportName
)) {
460
ScopedString
localName
(
scope
,
runtimeStrings
[
localExport
->
localName
]);
461
uint
index
=
module
()->
scope
->
internalClass
->
indexOfValueOrGetter
(
localName
->
toPropertyKey
());
462
if
(
index
==
UINT_MAX
)
463
return
nullptr
;
464
if
(
index
>=
module
()->
scope
->
locals
.
size
)
465
return
&(
imports
[
index
-
module
()->
scope
->
locals
.
size
]->
asValue
<
Value
>());
466
return
&
module
()->
scope
->
locals
[
index
];
467
}
468
469
if
(
auto
indirectExport
=
lookupNameInExportTable
(
470
data
->
indirectExportEntryTable
(),
data
->
indirectExportEntryTableSize
,
exportName
)) {
471
if
(
auto
module
=
dependentModule
(
urlAt
(
indirectExport
->
moduleRequest
))) {
472
ScopedString
importName
(
scope
,
runtimeStrings
[
indirectExport
->
importName
]);
473
return
module
->
resolveExportRecursively
(
importName
,
resolveSet
);
474
}
475
return
nullptr
;
476
}
477
478
if
(
exportName
->
toQString
() ==
QLatin1String
(
"default"
))
479
return
nullptr
;
480
481
const
Value
*
starResolution
=
nullptr
;
482
483
for
(
uint
i
= 0;
i
<
data
->
starExportEntryTableSize
; ++
i
) {
484
const
CompiledData
::
ExportEntry
&
entry
=
data
->
starExportEntryTable
()[
i
];
485
const
Value
*
resolution
=
nullptr
;
486
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
)))
487
resolution
=
module
->
resolveExportRecursively
(
exportName
,
resolveSet
);
488
489
// ### handle ambiguous
490
if
(
resolution
) {
491
if
(!
starResolution
) {
492
starResolution
=
resolution
;
493
continue
;
494
}
495
if
(
resolution
!=
starResolution
)
496
return
nullptr
;
497
}
498
}
499
500
return
starResolution
;
501
}
502
503
const
CompiledData
::
ExportEntry
*
ExecutableCompilationUnit
::
lookupNameInExportTable
(
504
const
CompiledData
::
ExportEntry
*
firstExportEntry
,
int
tableSize
,
QV4
::
String
*
name
)
const
505
{
506
const
CompiledData
::
ExportEntry
*
lastExportEntry
=
firstExportEntry
+
tableSize
;
507
auto
matchingExport
=
std
::
lower_bound
(
firstExportEntry
,
lastExportEntry
,
name
, [
this
](
const
CompiledData
::
ExportEntry
&
lhs
,
QV4
::
String
*
name
) {
508
return
stringAt
(
lhs
.
exportName
) <
name
->
toQString
();
509
});
510
if
(
matchingExport
==
lastExportEntry
||
stringAt
(
matchingExport
->
exportName
) !=
name
->
toQString
())
511
return
nullptr
;
512
return
matchingExport
;
513
}
514
515
void
ExecutableCompilationUnit
::
getExportedNamesRecursively
(
516
QStringList
*
names
,
QList
<
const
ExecutableCompilationUnit
*> *
exportNameSet
,
517
bool
includeDefaultExport
)
const
518
{
519
if
(
exportNameSet
->
contains
(
this
))
520
return
;
521
exportNameSet
->
append
(
this
);
522
523
const
auto
append
= [
names
,
includeDefaultExport
](
const
QString
&
name
) {
524
if
(!
includeDefaultExport
&&
name
==
QLatin1String
(
"default"
))
525
return
;
526
names
->
append
(
name
);
527
};
528
529
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
530
531
Q_ASSERT
(
data
);
532
Q_ASSERT
(
engine
);
533
534
for
(
uint
i
= 0;
i
<
data
->
localExportEntryTableSize
; ++
i
) {
535
const
CompiledData
::
ExportEntry
&
entry
=
data
->
localExportEntryTable
()[
i
];
536
append
(
stringAt
(
entry
.
exportName
));
537
}
538
539
for
(
uint
i
= 0;
i
<
data
->
indirectExportEntryTableSize
; ++
i
) {
540
const
CompiledData
::
ExportEntry
&
entry
=
data
->
indirectExportEntryTable
()[
i
];
541
append
(
stringAt
(
entry
.
exportName
));
542
}
543
544
for
(
uint
i
= 0;
i
<
data
->
starExportEntryTableSize
; ++
i
) {
545
const
CompiledData
::
ExportEntry
&
entry
=
data
->
starExportEntryTable
()[
i
];
546
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
547
module
->
getExportedNamesRecursively
(
548
names
,
exportNameSet
,
/*includeDefaultExport*/
false
);
549
}
550
}
551
}
552
553
void
ExecutableCompilationUnit
::
evaluate
()
554
{
555
Q_ASSERT
(
engine
);
556
557
QV4
::
Scope
scope
(
engine
);
558
QV4
::
Scoped
<
Module
>
mod
(
scope
,
module
());
559
mod
->
evaluate
();
560
}
561
562
void
ExecutableCompilationUnit
::
evaluateModuleRequests
()
563
{
564
Q_ASSERT
(
engine
);
565
566
const
CompiledData
::
Unit
*
data
=
unitData
();
567
for
(
uint
i
= 0,
end
=
data
->
moduleRequestTableSize
;
i
<
end
; ++
i
) {
568
auto
module
=
dependentModule
(
urlAt
(
data
->
moduleRequestTable
()[
i
]));
569
570
if
(
engine
->
hasException
)
571
return
;
572
573
Q_ASSERT
(
module
);
574
module
->
evaluate
();
575
if
(
engine
->
hasException
)
576
return
;
577
}
578
}
579
580
QString
ExecutableCompilationUnit
::
bindingValueAsString
(
const
CompiledData
::
Binding
*
binding
)
const
581
{
582
#
if
QT_CONFIG
(
translation
)
583
using
namespace
CompiledData
;
584
bool
byId
=
false
;
585
switch
(
binding
->
type
()) {
586
case
Binding
::
Type_TranslationById
:
587
byId
=
true
;
588
Q_FALLTHROUGH
();
589
case
Binding
::
Type_Translation
: {
590
return
translateFrom
({
binding
->
value
.
translationDataIndex
,
byId
});
591
}
592
default
:
593
break
;
594
}
595
#
endif
596
return
m_compilationUnit
->
bindingValueAsString
(
binding
);
597
}
598
599
QString
ExecutableCompilationUnit
::
translateFrom
(
TranslationDataIndex
index
)
const
600
{
601
#
if
!
QT_CONFIG
(
translation
)
602
return
QString
();
603
#
else
604
const
CompiledData
::
TranslationData
&
translation
=
unitData
()->
translations
()[
index
.
index
];
605
606
if
(
index
.
byId
) {
607
QByteArray
id
=
stringAt
(
translation
.
stringIndex
).
toUtf8
();
608
return
qtTrId
(
id
.
constData
(),
translation
.
number
);
609
}
610
611
const
auto
fileContext
= [
this
]() {
612
// This code must match that in the qsTr() implementation
613
const
QString
&
path
=
fileName
();
614
int
lastSlash
=
path
.
lastIndexOf
(
QLatin1Char
(
'/'
));
615
616
QStringView
context
= (
lastSlash
> -1)
617
?
QStringView
{
path
}.
mid
(
lastSlash
+ 1,
path
.
size
() -
lastSlash
- 5)
618
:
QStringView
();
619
return
context
.
toUtf8
();
620
};
621
622
const
bool
hasContext
623
=
translation
.
contextIndex
!=
QV4
::
CompiledData
::
TranslationData
::
NoContextIndex
;
624
QByteArray
context
;
625
if
(
hasContext
) {
626
context
=
stringAt
(
translation
.
contextIndex
).
toUtf8
();
627
}
else
{
628
auto
pragmaTranslationContext
=
unitData
()->
translationContextIndex
();
629
context
=
stringAt
(*
pragmaTranslationContext
).
toUtf8
();
630
context
=
context
.
isEmpty
() ?
fileContext
() :
context
;
631
}
632
633
QByteArray
comment
=
stringAt
(
translation
.
commentIndex
).
toUtf8
();
634
QByteArray
text
=
stringAt
(
translation
.
stringIndex
).
toUtf8
();
635
return
QCoreApplication
::
translate
(
context
,
text
,
comment
,
translation
.
number
);
636
#
endif
637
}
638
639
Heap
::
Module
*
ExecutableCompilationUnit
::
module
()
const
640
{
641
if
(
const
Module
*
m
=
m_valueOrModule
.
as
<
QV4
::
Module
>())
642
return
m
->
d
();
643
return
nullptr
;
644
}
645
646
void
ExecutableCompilationUnit
::
setModule
(
Heap
::
Module
*
module
)
647
{
648
// We don't necessarily hold any other references to ES modules. So, if the GC
649
// is running right now, we need to mark it. Otherwise it might collect it even
650
// though it's still reachable via the engine's list of compilation units.
651
QV4
::
WriteBarrier
::
markCustom
(
engine
, [
module
](
QV4
::
MarkStack
*
stack
) {
652
if
constexpr
(
QV4
::
WriteBarrier
::
isInsertionBarrier
) {
653
module
->
mark
(
stack
);
654
}
655
});
656
m_valueOrModule
=
module
;
657
}
658
659
}
// namespace QV4
660
661
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.18.0