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
.
isEmpty
());
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
,
QVector
<
ResolveSetEntry
> *
resolveSet
)
const
412
{
413
if
(!
module
())
414
return
nullptr
;
415
416
for
(
const
auto
&
entry
: *
resolveSet
)
417
if
(
entry
.
module
==
this
&&
entry
.
exportName
->
isEqualTo
(
exportName
))
418
return
nullptr
;
419
420
(*
resolveSet
) <<
ResolveSetEntry
(
this
,
exportName
);
421
422
if
(
exportName
->
toQString
() ==
QLatin1String
(
"*"
))
423
return
&
module
()->
self
;
424
425
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
426
427
Q_ASSERT
(
data
);
428
Q_ASSERT
(
engine
);
429
430
Scope
scope
(
engine
);
431
432
if
(
auto
localExport
=
lookupNameInExportTable
(
433
data
->
localExportEntryTable
(),
data
->
localExportEntryTableSize
,
exportName
)) {
434
ScopedString
localName
(
scope
,
runtimeStrings
[
localExport
->
localName
]);
435
uint
index
=
module
()->
scope
->
internalClass
->
indexOfValueOrGetter
(
localName
->
toPropertyKey
());
436
if
(
index
==
UINT_MAX
)
437
return
nullptr
;
438
if
(
index
>=
module
()->
scope
->
locals
.
size
)
439
return
&(
imports
[
index
-
module
()->
scope
->
locals
.
size
]->
asValue
<
Value
>());
440
return
&
module
()->
scope
->
locals
[
index
];
441
}
442
443
if
(
auto
indirectExport
=
lookupNameInExportTable
(
444
data
->
indirectExportEntryTable
(),
data
->
indirectExportEntryTableSize
,
exportName
)) {
445
if
(
auto
module
=
dependentModule
(
urlAt
(
indirectExport
->
moduleRequest
))) {
446
ScopedString
importName
(
scope
,
runtimeStrings
[
indirectExport
->
importName
]);
447
return
module
->
resolveExportRecursively
(
importName
,
resolveSet
);
448
}
449
return
nullptr
;
450
}
451
452
if
(
exportName
->
toQString
() ==
QLatin1String
(
"default"
))
453
return
nullptr
;
454
455
const
Value
*
starResolution
=
nullptr
;
456
457
for
(
uint
i
= 0;
i
<
data
->
starExportEntryTableSize
; ++
i
) {
458
const
CompiledData
::
ExportEntry
&
entry
=
data
->
starExportEntryTable
()[
i
];
459
const
Value
*
resolution
=
nullptr
;
460
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
)))
461
resolution
=
module
->
resolveExportRecursively
(
exportName
,
resolveSet
);
462
463
// ### handle ambiguous
464
if
(
resolution
) {
465
if
(!
starResolution
) {
466
starResolution
=
resolution
;
467
continue
;
468
}
469
if
(
resolution
!=
starResolution
)
470
return
nullptr
;
471
}
472
}
473
474
return
starResolution
;
475
}
476
477
const
CompiledData
::
ExportEntry
*
ExecutableCompilationUnit
::
lookupNameInExportTable
(
478
const
CompiledData
::
ExportEntry
*
firstExportEntry
,
int
tableSize
,
QV4
::
String
*
name
)
const
479
{
480
const
CompiledData
::
ExportEntry
*
lastExportEntry
=
firstExportEntry
+
tableSize
;
481
auto
matchingExport
=
std
::
lower_bound
(
firstExportEntry
,
lastExportEntry
,
name
, [
this
](
const
CompiledData
::
ExportEntry
&
lhs
,
QV4
::
String
*
name
) {
482
return
stringAt
(
lhs
.
exportName
) <
name
->
toQString
();
483
});
484
if
(
matchingExport
==
lastExportEntry
||
stringAt
(
matchingExport
->
exportName
) !=
name
->
toQString
())
485
return
nullptr
;
486
return
matchingExport
;
487
}
488
489
void
ExecutableCompilationUnit
::
getExportedNamesRecursively
(
490
QStringList
*
names
,
QVector
<
const
ExecutableCompilationUnit
*> *
exportNameSet
,
491
bool
includeDefaultExport
)
const
492
{
493
if
(
exportNameSet
->
contains
(
this
))
494
return
;
495
exportNameSet
->
append
(
this
);
496
497
const
auto
append
= [
names
,
includeDefaultExport
](
const
QString
&
name
) {
498
if
(!
includeDefaultExport
&&
name
==
QLatin1String
(
"default"
))
499
return
;
500
names
->
append
(
name
);
501
};
502
503
const
CompiledData
::
Unit
*
data
=
m_compilationUnit
->
data
;
504
505
Q_ASSERT
(
data
);
506
Q_ASSERT
(
engine
);
507
508
for
(
uint
i
= 0;
i
<
data
->
localExportEntryTableSize
; ++
i
) {
509
const
CompiledData
::
ExportEntry
&
entry
=
data
->
localExportEntryTable
()[
i
];
510
append
(
stringAt
(
entry
.
exportName
));
511
}
512
513
for
(
uint
i
= 0;
i
<
data
->
indirectExportEntryTableSize
; ++
i
) {
514
const
CompiledData
::
ExportEntry
&
entry
=
data
->
indirectExportEntryTable
()[
i
];
515
append
(
stringAt
(
entry
.
exportName
));
516
}
517
518
for
(
uint
i
= 0;
i
<
data
->
starExportEntryTableSize
; ++
i
) {
519
const
CompiledData
::
ExportEntry
&
entry
=
data
->
starExportEntryTable
()[
i
];
520
if
(
auto
module
=
dependentModule
(
urlAt
(
entry
.
moduleRequest
))) {
521
module
->
getExportedNamesRecursively
(
522
names
,
exportNameSet
,
/*includeDefaultExport*/
false
);
523
}
524
}
525
}
526
527
void
ExecutableCompilationUnit
::
evaluate
()
528
{
529
Q_ASSERT
(
engine
);
530
531
QV4
::
Scope
scope
(
engine
);
532
QV4
::
Scoped
<
Module
>
mod
(
scope
,
module
());
533
mod
->
evaluate
();
534
}
535
536
void
ExecutableCompilationUnit
::
evaluateModuleRequests
()
537
{
538
Q_ASSERT
(
engine
);
539
540
const
CompiledData
::
Unit
*
data
=
unitData
();
541
for
(
uint
i
= 0,
end
=
data
->
moduleRequestTableSize
;
i
<
end
; ++
i
) {
542
auto
module
=
dependentModule
(
urlAt
(
data
->
moduleRequestTable
()[
i
]));
543
544
if
(
engine
->
hasException
)
545
return
;
546
547
Q_ASSERT
(
module
);
548
module
->
evaluate
();
549
if
(
engine
->
hasException
)
550
return
;
551
}
552
}
553
554
QString
ExecutableCompilationUnit
::
bindingValueAsString
(
const
CompiledData
::
Binding
*
binding
)
const
555
{
556
#
if
QT_CONFIG
(
translation
)
557
using
namespace
CompiledData
;
558
bool
byId
=
false
;
559
switch
(
binding
->
type
()) {
560
case
Binding
::
Type_TranslationById
:
561
byId
=
true
;
562
Q_FALLTHROUGH
();
563
case
Binding
::
Type_Translation
: {
564
return
translateFrom
({
binding
->
value
.
translationDataIndex
,
byId
});
565
}
566
default
:
567
break
;
568
}
569
#
endif
570
return
m_compilationUnit
->
bindingValueAsString
(
binding
);
571
}
572
573
QString
ExecutableCompilationUnit
::
translateFrom
(
TranslationDataIndex
index
)
const
574
{
575
#
if
!
QT_CONFIG
(
translation
)
576
return
QString
();
577
#
else
578
const
CompiledData
::
TranslationData
&
translation
=
unitData
()->
translations
()[
index
.
index
];
579
580
if
(
index
.
byId
) {
581
QByteArray
id
=
stringAt
(
translation
.
stringIndex
).
toUtf8
();
582
return
qtTrId
(
id
.
constData
(),
translation
.
number
);
583
}
584
585
const
auto
fileContext
= [
this
]() {
586
// This code must match that in the qsTr() implementation
587
const
QString
&
path
=
fileName
();
588
int
lastSlash
=
path
.
lastIndexOf
(
QLatin1Char
(
'/'
));
589
590
QStringView
context
= (
lastSlash
> -1)
591
?
QStringView
{
path
}.
mid
(
lastSlash
+ 1,
path
.
size
() -
lastSlash
- 5)
592
:
QStringView
();
593
return
context
.
toUtf8
();
594
};
595
596
const
bool
hasContext
597
=
translation
.
contextIndex
!=
QV4
::
CompiledData
::
TranslationData
::
NoContextIndex
;
598
QByteArray
context
;
599
if
(
hasContext
) {
600
context
=
stringAt
(
translation
.
contextIndex
).
toUtf8
();
601
}
else
{
602
auto
pragmaTranslationContext
=
unitData
()->
translationContextIndex
();
603
context
=
stringAt
(*
pragmaTranslationContext
).
toUtf8
();
604
context
=
context
.
isEmpty
() ?
fileContext
() :
context
;
605
}
606
607
QByteArray
comment
=
stringAt
(
translation
.
commentIndex
).
toUtf8
();
608
QByteArray
text
=
stringAt
(
translation
.
stringIndex
).
toUtf8
();
609
return
QCoreApplication
::
translate
(
context
,
text
,
comment
,
translation
.
number
);
610
#
endif
611
}
612
613
Heap
::
Module
*
ExecutableCompilationUnit
::
module
()
const
614
{
615
if
(
const
Module
*
m
=
m_valueOrModule
.
as
<
QV4
::
Module
>())
616
return
m
->
d
();
617
return
nullptr
;
618
}
619
620
void
ExecutableCompilationUnit
::
setModule
(
Heap
::
Module
*
module
)
621
{
622
m_valueOrModule
=
module
;
623
}
624
625
}
// namespace QV4
626
627
QT_END_NAMESPACE
QPlatformGraphicsBufferHelper
\inmodule QtGui
QV4
Definition
qjsvalue.h:23
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.14.0