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