arkanalyzer 1.0.91 → 1.0.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Scene.d.ts +15 -0
- package/lib/Scene.d.ts.map +1 -1
- package/lib/Scene.js +39 -0
- package/lib/callgraph/algorithm/AbstractAnalysis.d.ts +6 -0
- package/lib/callgraph/algorithm/AbstractAnalysis.d.ts.map +1 -1
- package/lib/callgraph/algorithm/AbstractAnalysis.js +17 -8
- package/lib/callgraph/algorithm/ClassHierarchyAnalysis.d.ts +1 -0
- package/lib/callgraph/algorithm/ClassHierarchyAnalysis.d.ts.map +1 -1
- package/lib/callgraph/algorithm/ClassHierarchyAnalysis.js +9 -3
- package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts +147 -0
- package/lib/callgraph/algorithm/RapidTypeAnalysis.d.ts.map +1 -1
- package/lib/callgraph/algorithm/RapidTypeAnalysis.js +803 -76
- package/lib/callgraph/model/CallGraph.d.ts +1 -0
- package/lib/callgraph/model/CallGraph.d.ts.map +1 -1
- package/lib/callgraph/model/CallGraph.js +4 -0
- package/lib/callgraph/model/CallSite.d.ts +88 -1
- package/lib/callgraph/model/CallSite.d.ts.map +1 -1
- package/lib/callgraph/model/CallSite.js +58 -4
- package/lib/core/common/ArkIRTransformer.d.ts.map +1 -1
- package/lib/core/common/ArkIRTransformer.js +1 -1
- package/lib/core/common/IRInference.js +2 -2
- package/lib/core/common/SdkUtils.js +1 -1
- package/lib/core/common/TypeInference.d.ts.map +1 -1
- package/lib/core/common/TypeInference.js +3 -0
- package/lib/core/graph/builder/SwitchBuilder.d.ts.map +1 -1
- package/lib/core/graph/builder/SwitchBuilder.js +11 -1
- package/lib/core/graph/builder/ViewTreeBuilder.d.ts +13 -3
- package/lib/core/graph/builder/ViewTreeBuilder.d.ts.map +1 -1
- package/lib/core/graph/builder/ViewTreeBuilder.js +271 -86
- package/lib/core/model/ArkModule.d.ts +9 -12
- package/lib/core/model/ArkModule.d.ts.map +1 -1
- package/lib/core/model/ArkModule.js +7 -10
- package/lib/core/model/builder/ArkClassBuilder.js +10 -4
- package/lib/core/model/builder/ArkMethodBuilder.d.ts +2 -1
- package/lib/core/model/builder/ArkMethodBuilder.d.ts.map +1 -1
- package/lib/core/model/builder/ArkMethodBuilder.js +5 -1
- package/lib/frontend/FrontendBuilder.d.ts +8 -10
- package/lib/frontend/FrontendBuilder.d.ts.map +1 -1
- package/lib/frontend/FrontendBuilder.js +9 -17
- package/lib/frontend/common/ModuleAnalysisConfig.d.ts +8 -1
- package/lib/frontend/common/ModuleAnalysisConfig.d.ts.map +1 -1
- package/lib/frontend/common/ModuleAnalysisConfig.js +10 -1
- package/lib/frontend/common/ModuleBuilder.d.ts +44 -33
- package/lib/frontend/common/ModuleBuilder.d.ts.map +1 -1
- package/lib/frontend/common/ModuleBuilder.js +195 -66
- package/lib/frontend/common/ModuleCache.d.ts +1 -0
- package/lib/frontend/common/ModuleCache.d.ts.map +1 -1
- package/lib/frontend/common/ModuleCache.js +1 -0
- package/lib/frontend/common/ModuleDepth.d.ts +19 -14
- package/lib/frontend/common/ModuleDepth.d.ts.map +1 -1
- package/lib/frontend/common/ModuleDepth.js +25 -15
- package/lib/frontend/cppFrontend/graph/builder/SwitchBuilder.d.ts.map +1 -1
- package/lib/frontend/cppFrontend/graph/builder/SwitchBuilder.js +11 -1
- package/package.json +1 -1
|
@@ -52,26 +52,39 @@ const ModelUtils_1 = require("../../common/ModelUtils");
|
|
|
52
52
|
const Const_1 = require("../../common/Const");
|
|
53
53
|
const logger = logger_1.default.getLogger(logger_1.LOG_MODULE_TYPE.ARKANALYZER, 'ViewTreeBuilder');
|
|
54
54
|
const COMPONENT_CREATE_FUNCTIONS = new Set([EtsConst_1.COMPONENT_CREATE_FUNCTION, EtsConst_1.COMPONENT_BRANCH_FUNCTION]);
|
|
55
|
-
|
|
55
|
+
const BEHAVIOR_PARSER_KEYS = new Set(['tabBar', 'navDestination', 'bindContextMenu', 'bindMenu', 'bindContentCover', 'bindSheet', 'bindPopup']);
|
|
56
|
+
function backtraceLocalInitValue(value, visited = new Set()) {
|
|
57
|
+
if (visited.has(value)) {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
visited.add(value);
|
|
56
61
|
let stmt = value.getDeclaringStmt();
|
|
57
62
|
if (stmt instanceof Stmt_1.ArkAssignStmt) {
|
|
58
63
|
let rightOp = stmt.getRightOp();
|
|
59
64
|
if (rightOp instanceof Local_1.Local) {
|
|
60
|
-
return backtraceLocalInitValue(rightOp);
|
|
65
|
+
return backtraceLocalInitValue(rightOp, visited);
|
|
61
66
|
}
|
|
62
67
|
else if (rightOp instanceof Ref_1.ArkArrayRef) {
|
|
63
|
-
|
|
68
|
+
let base = rightOp.getBase();
|
|
69
|
+
if (base instanceof Local_1.Local) {
|
|
70
|
+
return backtraceLocalInitValue(base, visited);
|
|
71
|
+
}
|
|
72
|
+
return rightOp;
|
|
64
73
|
}
|
|
65
74
|
return rightOp;
|
|
66
75
|
}
|
|
67
76
|
return value;
|
|
68
77
|
}
|
|
69
|
-
function parseObjectLiteral(objectLiteralCls, scene) {
|
|
78
|
+
function parseObjectLiteral(objectLiteralCls, scene, visited = new Set()) {
|
|
70
79
|
let map = new Map();
|
|
71
|
-
if (
|
|
80
|
+
if (!objectLiteralCls || objectLiteralCls.getCategory() !== ArkClass_1.ClassCategory.OBJECT) {
|
|
72
81
|
return map;
|
|
73
82
|
}
|
|
74
|
-
|
|
83
|
+
if (visited.has(objectLiteralCls)) {
|
|
84
|
+
return map;
|
|
85
|
+
}
|
|
86
|
+
visited.add(objectLiteralCls);
|
|
87
|
+
objectLiteralCls.getFields().forEach(field => {
|
|
75
88
|
let stmts = field.getInitializer();
|
|
76
89
|
if (stmts.length === 0) {
|
|
77
90
|
return;
|
|
@@ -87,7 +100,7 @@ function parseObjectLiteral(objectLiteralCls, scene) {
|
|
|
87
100
|
map.set(field, value);
|
|
88
101
|
if (value instanceof Expr_1.ArkNewExpr) {
|
|
89
102
|
let subCls = ModelUtils_1.ModelUtils.getArkClassInBuild(scene, value.getClassType());
|
|
90
|
-
let childMap = parseObjectLiteral(subCls, scene);
|
|
103
|
+
let childMap = parseObjectLiteral(subCls, scene, visited);
|
|
91
104
|
if (childMap) {
|
|
92
105
|
map.set(field, childMap);
|
|
93
106
|
}
|
|
@@ -97,30 +110,79 @@ function parseObjectLiteral(objectLiteralCls, scene) {
|
|
|
97
110
|
}
|
|
98
111
|
class StateValuesUtils {
|
|
99
112
|
constructor(declaringArkClass) {
|
|
113
|
+
this.stmtStateCache = new Map();
|
|
114
|
+
// Instance-level recursion guards — detect cycles within a single synchronous build.
|
|
115
|
+
// Unlike the original per-call-chain `visitor` parameter, these are instance state, so they
|
|
116
|
+
// assume single-threaded execution. If async/parallel builds are introduced in the future,
|
|
117
|
+
// these must be replaced with per-call-chain visitors to avoid false-positive cycle detection.
|
|
118
|
+
this.computingStmts = new Set();
|
|
119
|
+
this.computingMethods = new Set();
|
|
120
|
+
this.methodStateCache = new Map();
|
|
100
121
|
this.declaringArkClass = declaringArkClass;
|
|
101
122
|
}
|
|
102
123
|
static getInstance(declaringArkClass) {
|
|
103
|
-
|
|
124
|
+
let inst = StateValuesUtils.cache.get(declaringArkClass);
|
|
125
|
+
if (!inst) {
|
|
126
|
+
inst = new StateValuesUtils(declaringArkClass);
|
|
127
|
+
StateValuesUtils.cache.set(declaringArkClass, inst);
|
|
128
|
+
}
|
|
129
|
+
if (StateValuesUtils.activeBuildCount > 0) {
|
|
130
|
+
StateValuesUtils.usedInstances.add(inst);
|
|
131
|
+
}
|
|
132
|
+
return inst;
|
|
133
|
+
}
|
|
134
|
+
static beginBuild() {
|
|
135
|
+
StateValuesUtils.activeBuildCount++;
|
|
136
|
+
}
|
|
137
|
+
static endBuild() {
|
|
138
|
+
StateValuesUtils.activeBuildCount--;
|
|
139
|
+
if (StateValuesUtils.activeBuildCount === 0) {
|
|
140
|
+
for (const inst of StateValuesUtils.usedInstances) {
|
|
141
|
+
inst.stmtStateCache.clear();
|
|
142
|
+
inst.methodStateCache.clear();
|
|
143
|
+
}
|
|
144
|
+
StateValuesUtils.usedInstances.clear();
|
|
145
|
+
}
|
|
104
146
|
}
|
|
105
|
-
parseStmtUsesStateValues(stmt, uses = new Set(), wholeMethod = false
|
|
106
|
-
|
|
147
|
+
parseStmtUsesStateValues(stmt, uses = new Set(), wholeMethod = false) {
|
|
148
|
+
const isCacheable = !wholeMethod;
|
|
149
|
+
if (isCacheable) {
|
|
150
|
+
const cached = this.stmtStateCache.get(stmt);
|
|
151
|
+
if (cached) {
|
|
152
|
+
for (const f of cached) {
|
|
153
|
+
uses.add(f);
|
|
154
|
+
}
|
|
155
|
+
return uses;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (this.computingStmts.has(stmt)) {
|
|
107
159
|
return uses;
|
|
108
160
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
values
|
|
161
|
+
this.computingStmts.add(stmt);
|
|
162
|
+
const targetUses = isCacheable ? new Set() : uses;
|
|
163
|
+
try {
|
|
164
|
+
let values = stmt.getUses();
|
|
165
|
+
if (stmt instanceof Stmt_1.ArkAssignStmt) {
|
|
166
|
+
values.push(stmt.getLeftOp());
|
|
167
|
+
}
|
|
168
|
+
for (const v of values) {
|
|
169
|
+
this.parseValueUsesStateValues(v, targetUses, wholeMethod);
|
|
170
|
+
}
|
|
113
171
|
}
|
|
114
|
-
|
|
115
|
-
this.
|
|
172
|
+
finally {
|
|
173
|
+
this.computingStmts.delete(stmt);
|
|
174
|
+
}
|
|
175
|
+
if (isCacheable) {
|
|
176
|
+
this.stmtStateCache.set(stmt, targetUses);
|
|
177
|
+
for (const f of targetUses) {
|
|
178
|
+
uses.add(f);
|
|
179
|
+
}
|
|
116
180
|
}
|
|
117
181
|
return uses;
|
|
118
182
|
}
|
|
119
183
|
objectLiteralMapUsedStateValues(uses, map) {
|
|
120
184
|
for (const [_, value] of map) {
|
|
121
185
|
if (value instanceof Ref_1.ArkInstanceFieldRef) {
|
|
122
|
-
// Field ref may come from intermediate objects (e.g. this.lastAppInfo?.message),
|
|
123
|
-
// ensure we trace its base to catch state-field origins.
|
|
124
186
|
this.parseValueUsesStateValues(value.getBase(), uses);
|
|
125
187
|
let srcField = this.declaringArkClass.getFieldWithName(value.getFieldName());
|
|
126
188
|
let decorators = srcField === null || srcField === void 0 ? void 0 : srcField.getStateDecorators();
|
|
@@ -145,16 +207,51 @@ class StateValuesUtils {
|
|
|
145
207
|
return uses;
|
|
146
208
|
}
|
|
147
209
|
let cls = ModelUtils_1.ModelUtils.getArkClassInBuild(this.declaringArkClass.getDeclaringArkFile().getScene(), type);
|
|
148
|
-
let map =
|
|
210
|
+
let map = this.getObjectLiteralMap(cls);
|
|
149
211
|
this.objectLiteralMapUsedStateValues(uses, map);
|
|
150
212
|
return uses;
|
|
151
213
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
214
|
+
static getCachedObjectLiteral(cls, scene) {
|
|
215
|
+
if (!cls || cls.getCategory() !== ArkClass_1.ClassCategory.OBJECT) {
|
|
216
|
+
return new Map();
|
|
217
|
+
}
|
|
218
|
+
let cached = StateValuesUtils.objectLiteralCache.get(cls);
|
|
219
|
+
if (cached) {
|
|
220
|
+
return cached;
|
|
221
|
+
}
|
|
222
|
+
let map = parseObjectLiteral(cls, scene);
|
|
223
|
+
StateValuesUtils.objectLiteralCache.set(cls, map);
|
|
224
|
+
return map;
|
|
225
|
+
}
|
|
226
|
+
getObjectLiteralMap(cls) {
|
|
227
|
+
return StateValuesUtils.getCachedObjectLiteral(cls, this.declaringArkClass.getDeclaringArkFile().getScene());
|
|
228
|
+
}
|
|
229
|
+
parseMethodUsesStateValues(methodSignature, uses) {
|
|
230
|
+
const cached = this.methodStateCache.get(methodSignature);
|
|
231
|
+
if (cached) {
|
|
232
|
+
for (const f of cached) {
|
|
233
|
+
uses.add(f);
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (this.computingMethods.has(methodSignature)) {
|
|
155
238
|
return;
|
|
156
239
|
}
|
|
157
|
-
|
|
240
|
+
this.computingMethods.add(methodSignature);
|
|
241
|
+
const targetUses = new Set();
|
|
242
|
+
try {
|
|
243
|
+
this.collectMethodStateValues(methodSignature, targetUses);
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
this.computingMethods.delete(methodSignature);
|
|
247
|
+
}
|
|
248
|
+
this.methodStateCache.set(methodSignature, targetUses);
|
|
249
|
+
for (const f of targetUses) {
|
|
250
|
+
uses.add(f);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
collectMethodStateValues(methodSignature, targetUses) {
|
|
254
|
+
var _a;
|
|
158
255
|
let method = this.declaringArkClass.getDeclaringArkFile().getScene().getMethod(methodSignature);
|
|
159
256
|
if (!method) {
|
|
160
257
|
return;
|
|
@@ -164,10 +261,10 @@ class StateValuesUtils {
|
|
|
164
261
|
return;
|
|
165
262
|
}
|
|
166
263
|
for (const stmt of stmts) {
|
|
167
|
-
this.parseStmtUsesStateValues(stmt,
|
|
264
|
+
this.parseStmtUsesStateValues(stmt, targetUses, true);
|
|
168
265
|
}
|
|
169
266
|
}
|
|
170
|
-
parseValueUsesStateValues(v, uses = new Set(), wholeMethod = false
|
|
267
|
+
parseValueUsesStateValues(v, uses = new Set(), wholeMethod = false) {
|
|
171
268
|
if (v instanceof Ref_1.ArkInstanceFieldRef) {
|
|
172
269
|
let field = this.declaringArkClass.getField(v.getFieldSignature());
|
|
173
270
|
let decorators = field === null || field === void 0 ? void 0 : field.getStateDecorators();
|
|
@@ -176,49 +273,59 @@ class StateValuesUtils {
|
|
|
176
273
|
}
|
|
177
274
|
}
|
|
178
275
|
else if (v instanceof Ref_1.ArkArrayRef) {
|
|
179
|
-
this.parseValueUsesStateValues(v.getBase(), uses, wholeMethod
|
|
180
|
-
this.parseValueUsesStateValues(v.getIndex(), uses, wholeMethod
|
|
276
|
+
this.parseValueUsesStateValues(v.getBase(), uses, wholeMethod);
|
|
277
|
+
this.parseValueUsesStateValues(v.getIndex(), uses, wholeMethod);
|
|
181
278
|
}
|
|
182
279
|
else if (v instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
183
|
-
this.parseValueUsesStateValues(v.getBase(), uses, wholeMethod
|
|
280
|
+
this.parseValueUsesStateValues(v.getBase(), uses, wholeMethod);
|
|
184
281
|
for (const arg of v.getArgs()) {
|
|
185
|
-
this.parseValueUsesStateValues(arg, uses, wholeMethod
|
|
282
|
+
this.parseValueUsesStateValues(arg, uses, wholeMethod);
|
|
186
283
|
}
|
|
187
|
-
this.parseMethodUsesStateValues(v.getMethodSignature(), uses
|
|
284
|
+
this.parseMethodUsesStateValues(v.getMethodSignature(), uses);
|
|
188
285
|
}
|
|
189
286
|
else if (v instanceof Expr_1.ArkStaticInvokeExpr) {
|
|
190
287
|
for (const arg of v.getArgs()) {
|
|
191
|
-
this.parseValueUsesStateValues(arg, uses, wholeMethod
|
|
288
|
+
this.parseValueUsesStateValues(arg, uses, wholeMethod);
|
|
192
289
|
}
|
|
193
290
|
}
|
|
194
291
|
else if (v instanceof Expr_1.ArkPtrInvokeExpr) {
|
|
195
|
-
this.parseValueUsesStateValues(v.getFuncPtrLocal(), uses, wholeMethod
|
|
292
|
+
this.parseValueUsesStateValues(v.getFuncPtrLocal(), uses, wholeMethod);
|
|
196
293
|
for (const arg of v.getArgs()) {
|
|
197
|
-
this.parseValueUsesStateValues(arg, uses, wholeMethod
|
|
294
|
+
this.parseValueUsesStateValues(arg, uses, wholeMethod);
|
|
198
295
|
}
|
|
199
296
|
}
|
|
200
297
|
else if (v instanceof Expr_1.ArkNormalBinopExpr || v instanceof Expr_1.ArkConditionExpr) {
|
|
201
|
-
this.parseValueUsesStateValues(v.getOp1(), uses, wholeMethod
|
|
202
|
-
this.parseValueUsesStateValues(v.getOp2(), uses, wholeMethod
|
|
298
|
+
this.parseValueUsesStateValues(v.getOp1(), uses, wholeMethod);
|
|
299
|
+
this.parseValueUsesStateValues(v.getOp2(), uses, wholeMethod);
|
|
203
300
|
}
|
|
204
301
|
else if (v instanceof Local_1.Local) {
|
|
205
|
-
|
|
206
|
-
return uses;
|
|
207
|
-
}
|
|
208
|
-
let type = v.getType();
|
|
209
|
-
if (type instanceof Type_1.FunctionType) {
|
|
210
|
-
this.parseMethodUsesStateValues(type.getMethodSignature(), uses, visitor);
|
|
211
|
-
return uses;
|
|
212
|
-
}
|
|
213
|
-
this.parseObjectUsedStateValues(type, uses);
|
|
214
|
-
let declaringStmt = v.getDeclaringStmt();
|
|
215
|
-
if (!wholeMethod && declaringStmt) {
|
|
216
|
-
this.parseStmtUsesStateValues(declaringStmt, uses, wholeMethod, visitor);
|
|
217
|
-
}
|
|
302
|
+
this.parseLocalUsesStateValues(v, uses, wholeMethod);
|
|
218
303
|
}
|
|
219
304
|
return uses;
|
|
220
305
|
}
|
|
306
|
+
parseLocalUsesStateValues(v, uses, wholeMethod) {
|
|
307
|
+
if (v.getName() === 'this') {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
let type = v.getType();
|
|
311
|
+
if (type instanceof Type_1.FunctionType) {
|
|
312
|
+
this.parseMethodUsesStateValues(type.getMethodSignature(), uses);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
this.parseObjectUsedStateValues(type, uses);
|
|
316
|
+
let declaringStmt = v.getDeclaringStmt();
|
|
317
|
+
if (!wholeMethod && declaringStmt) {
|
|
318
|
+
this.parseStmtUsesStateValues(declaringStmt, uses, wholeMethod);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
221
321
|
}
|
|
322
|
+
StateValuesUtils.cache = new WeakMap();
|
|
323
|
+
// ObjectLiteral parse results are deterministic and cached permanently (WeakMap keyed by ArkClass).
|
|
324
|
+
// Not cleared in endBuild() — safe while ArkClass fields are immutable. If incremental
|
|
325
|
+
// builds ever mutate ArkClass fields, this cache must be invalidated accordingly.
|
|
326
|
+
StateValuesUtils.objectLiteralCache = new WeakMap();
|
|
327
|
+
StateValuesUtils.activeBuildCount = 0;
|
|
328
|
+
StateValuesUtils.usedInstances = new Set();
|
|
222
329
|
var ViewTreeNodeType;
|
|
223
330
|
(function (ViewTreeNodeType) {
|
|
224
331
|
ViewTreeNodeType[ViewTreeNodeType["SystemComponent"] = 0] = "SystemComponent";
|
|
@@ -303,6 +410,9 @@ class ViewTreeNodeImpl {
|
|
|
303
410
|
this.type = ViewTreeNodeType.Builder;
|
|
304
411
|
this.signature = builder.getSignature();
|
|
305
412
|
this.classSignature = this.signature;
|
|
413
|
+
if (ViewTreeImpl.isBuilding(builder.getSignature())) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
306
416
|
const root = (_a = builder.getViewTree()) === null || _a === void 0 ? void 0 : _a.getRoot();
|
|
307
417
|
if (root) {
|
|
308
418
|
for (let child of root.children) {
|
|
@@ -378,7 +488,7 @@ class ViewTreeNodeImpl {
|
|
|
378
488
|
}
|
|
379
489
|
}
|
|
380
490
|
let builderNode;
|
|
381
|
-
if (
|
|
491
|
+
if (BEHAVIOR_PARSER_KEYS.has(key) && expr instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
382
492
|
let parseFn = tree.COMPONENT_BEHAVIOR_PARSERS.get(key);
|
|
383
493
|
if (parseFn) {
|
|
384
494
|
builderNode = parseFn(local2Node, stmt, expr);
|
|
@@ -508,28 +618,23 @@ class TreeNodeStack {
|
|
|
508
618
|
}
|
|
509
619
|
}
|
|
510
620
|
class ViewTreeImpl extends TreeNodeStack {
|
|
621
|
+
static isBuilding(sig) {
|
|
622
|
+
return ViewTreeImpl.buildingTrees.has(sig);
|
|
623
|
+
}
|
|
624
|
+
static beginBatchBuild() {
|
|
625
|
+
StateValuesUtils.beginBuild();
|
|
626
|
+
}
|
|
627
|
+
static endBatchBuild() {
|
|
628
|
+
StateValuesUtils.endBuild();
|
|
629
|
+
}
|
|
511
630
|
/**
|
|
512
631
|
* @internal
|
|
513
632
|
*/
|
|
514
633
|
constructor(render) {
|
|
515
634
|
super();
|
|
516
|
-
this.
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
['Repeat.create', this.repeatCreationParser.bind(this)],
|
|
520
|
-
['View.create', this.viewComponentCreationParser.bind(this)],
|
|
521
|
-
['If.branch', this.ifBranchCreationParser.bind(this)],
|
|
522
|
-
['WaterFlow.create', this.waterFlowCreationParser.bind(this)],
|
|
523
|
-
]);
|
|
524
|
-
this.COMPONENT_BEHAVIOR_PARSERS = new Map([
|
|
525
|
-
['tabBar', this.tabBarComponentParser.bind(this)],
|
|
526
|
-
['navDestination', this.navDestinationComponentParser.bind(this)],
|
|
527
|
-
['bindContextMenu', this.bindContextMenuComponentParser.bind(this)],
|
|
528
|
-
['bindMenu', this.bindContextMenuComponentParser.bind(this)],
|
|
529
|
-
['bindContentCover', this.bindContentCoverComponentParser.bind(this)],
|
|
530
|
-
['bindSheet', this.bindContentCoverComponentParser.bind(this)],
|
|
531
|
-
['bindPopup', this.bindPopupComponentParser.bind(this)],
|
|
532
|
-
]);
|
|
635
|
+
this.containsBuilderParam = false;
|
|
636
|
+
this._createParsers = null;
|
|
637
|
+
this._behaviorParsers = null;
|
|
533
638
|
this.render = render;
|
|
534
639
|
this.stateValues = new Map();
|
|
535
640
|
this.fieldTypes = new Map();
|
|
@@ -571,15 +676,36 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
571
676
|
return;
|
|
572
677
|
}
|
|
573
678
|
this.buildViewStatus = true;
|
|
574
|
-
|
|
679
|
+
let sig;
|
|
575
680
|
if (this.render.hasBuilderDecorator()) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
this.
|
|
681
|
+
sig = this.render.getSignature();
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
sig = this.render.getDeclaringArkClass().getSignature();
|
|
685
|
+
}
|
|
686
|
+
if (ViewTreeImpl.buildingTrees.has(sig)) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
ViewTreeImpl.buildingTrees.add(sig);
|
|
690
|
+
StateValuesUtils.beginBuild();
|
|
691
|
+
try {
|
|
692
|
+
this.loadClasssFieldTypes();
|
|
693
|
+
if (this.render.hasBuilderDecorator()) {
|
|
694
|
+
let node = ViewTreeNodeImpl.createBuilderNode();
|
|
695
|
+
node.signature = this.render.getSignature();
|
|
696
|
+
node.classSignature = node.signature;
|
|
697
|
+
this.push(node);
|
|
698
|
+
}
|
|
699
|
+
if (this.render.getCfg()) {
|
|
700
|
+
this.buildViewTreeFromCfg(this.render.getCfg());
|
|
701
|
+
}
|
|
580
702
|
}
|
|
581
|
-
|
|
582
|
-
|
|
703
|
+
catch (e) {
|
|
704
|
+
logger.error(`ViewTree build failed for ${this.render.getSignature().toString()}: ${e instanceof Error ? e.message : String(e)}`);
|
|
705
|
+
}
|
|
706
|
+
finally {
|
|
707
|
+
ViewTreeImpl.buildingTrees.delete(sig);
|
|
708
|
+
StateValuesUtils.endBuild();
|
|
583
709
|
}
|
|
584
710
|
}
|
|
585
711
|
/**
|
|
@@ -592,11 +718,12 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
592
718
|
* @internal
|
|
593
719
|
*/
|
|
594
720
|
addStateValue(field, node) {
|
|
595
|
-
|
|
596
|
-
|
|
721
|
+
let nodes = this.stateValues.get(field);
|
|
722
|
+
if (!nodes) {
|
|
723
|
+
nodes = new Set();
|
|
724
|
+
this.stateValues.set(field, nodes);
|
|
597
725
|
}
|
|
598
|
-
|
|
599
|
-
sets === null || sets === void 0 ? void 0 : sets.add(node);
|
|
726
|
+
nodes.add(node);
|
|
600
727
|
}
|
|
601
728
|
/**
|
|
602
729
|
* @internal
|
|
@@ -612,6 +739,7 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
612
739
|
this.fieldTypes.set(field.getName(), decorators[0]);
|
|
613
740
|
}
|
|
614
741
|
else {
|
|
742
|
+
// TODO: 存在多个状态装饰器的情况如state和watch
|
|
615
743
|
this.fieldTypes.set(field.getName(), decorators[0]);
|
|
616
744
|
}
|
|
617
745
|
}
|
|
@@ -701,6 +829,17 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
701
829
|
* @internal
|
|
702
830
|
*/
|
|
703
831
|
addBuilderNode(method, shouldPush = true) {
|
|
832
|
+
let builderSig = method.getSignature();
|
|
833
|
+
if (ViewTreeImpl.buildingTrees.has(builderSig)) {
|
|
834
|
+
let node = ViewTreeNodeImpl.createBuilderNode();
|
|
835
|
+
node.signature = builderSig;
|
|
836
|
+
node.classSignature = builderSig;
|
|
837
|
+
if (shouldPush) {
|
|
838
|
+
this.push(node);
|
|
839
|
+
this.pop();
|
|
840
|
+
}
|
|
841
|
+
return node;
|
|
842
|
+
}
|
|
704
843
|
let builderViewTree = method.getViewTree();
|
|
705
844
|
if (!builderViewTree || !builderViewTree.getRoot()) {
|
|
706
845
|
logger.error(`ViewTree->addBuilderNode ${method.getSignature().toString()} build viewtree fail.`);
|
|
@@ -746,18 +885,30 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
746
885
|
});
|
|
747
886
|
}
|
|
748
887
|
this.push(node);
|
|
888
|
+
let clsSig = cls.getSignature();
|
|
889
|
+
if (ViewTreeImpl.buildingTrees.has(clsSig)) {
|
|
890
|
+
return node;
|
|
891
|
+
}
|
|
749
892
|
let componentViewTree = cls.getViewTree();
|
|
750
893
|
if (!componentViewTree || !componentViewTree.getRoot()) {
|
|
751
894
|
logger.error(`ViewTree->addCustomComponentNode ${cls.getSignature().toString()} build viewtree fail.`);
|
|
752
895
|
return node;
|
|
753
896
|
}
|
|
754
897
|
let root = componentViewTree.getRoot();
|
|
755
|
-
if (
|
|
898
|
+
if (componentViewTree.containsBuilderParam) {
|
|
756
899
|
root = this.cloneBuilderParamNode(node, root);
|
|
757
900
|
}
|
|
758
901
|
node.children.push(root);
|
|
759
902
|
return node;
|
|
760
903
|
}
|
|
904
|
+
/** CustomComponent leaf when ArkClass is gone; signature from Scene.customComponentMap. */
|
|
905
|
+
addCustomComponentStubNode(signature) {
|
|
906
|
+
const node = ViewTreeNodeImpl.createCustomComponent();
|
|
907
|
+
node.signature = signature;
|
|
908
|
+
node.classSignature = signature;
|
|
909
|
+
this.push(node);
|
|
910
|
+
return node;
|
|
911
|
+
}
|
|
761
912
|
cloneBuilderParamNode(node, root) {
|
|
762
913
|
root = root.clone(node);
|
|
763
914
|
if (node.stateValuesTransfer) {
|
|
@@ -782,6 +933,7 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
782
933
|
addBuilderParamNode(field) {
|
|
783
934
|
let node = ViewTreeNodeImpl.createBuilderParamNode();
|
|
784
935
|
node.builderParam = field;
|
|
936
|
+
this.containsBuilderParam = true;
|
|
785
937
|
this.push(node);
|
|
786
938
|
this.pop();
|
|
787
939
|
return node;
|
|
@@ -879,15 +1031,16 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
879
1031
|
viewComponentCreationParser(name, stmt, expr) {
|
|
880
1032
|
let temp = expr.getArg(0);
|
|
881
1033
|
let arg;
|
|
882
|
-
temp.getUsedStmts()
|
|
883
|
-
if (
|
|
884
|
-
const rightOp =
|
|
1034
|
+
for (const usedStmt of temp.getUsedStmts()) {
|
|
1035
|
+
if (usedStmt instanceof Stmt_1.ArkAssignStmt && usedStmt.getRightOp() instanceof Expr_1.ArkInstanceInvokeExpr) {
|
|
1036
|
+
const rightOp = usedStmt.getRightOp();
|
|
885
1037
|
const methodName = rightOp.getMethodSignature().getMethodSubSignature().getMethodName();
|
|
886
1038
|
if (methodName === 'constructor') {
|
|
887
1039
|
arg = rightOp.getArg(0);
|
|
1040
|
+
break;
|
|
888
1041
|
}
|
|
889
1042
|
}
|
|
890
|
-
}
|
|
1043
|
+
}
|
|
891
1044
|
let builderMethod;
|
|
892
1045
|
let builder = expr.getArg(1);
|
|
893
1046
|
if (builder) {
|
|
@@ -916,9 +1069,12 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
916
1069
|
if (cls && cls.hasComponentDecorator()) {
|
|
917
1070
|
return this.addCustomComponentNode(cls, arg, builderMethod);
|
|
918
1071
|
}
|
|
919
|
-
|
|
920
|
-
|
|
1072
|
+
// Providing module IR may be gone — look up custom component table.
|
|
1073
|
+
const stubSig = this.render.getDeclaringArkFile().getScene().getCustomComponent(clsSignature.getClassName());
|
|
1074
|
+
if (stubSig) {
|
|
1075
|
+
return this.addCustomComponentStubNode(stubSig);
|
|
921
1076
|
}
|
|
1077
|
+
logger.error(`ViewTree->viewComponentCreationParser not found class ${clsSignature.toString()}. ${stmt.toString()}`);
|
|
922
1078
|
}
|
|
923
1079
|
return undefined;
|
|
924
1080
|
}
|
|
@@ -980,6 +1136,33 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
980
1136
|
this.popComponentExpect(EtsConst_1.COMPONENT_IF);
|
|
981
1137
|
return this.addSystemComponentNode(EtsConst_1.COMPONENT_IF_BRANCH);
|
|
982
1138
|
}
|
|
1139
|
+
get COMPONENT_CREATE_PARSERS() {
|
|
1140
|
+
if (!this._createParsers) {
|
|
1141
|
+
this._createParsers = new Map([
|
|
1142
|
+
['ForEach.create', this.forEachCreationParser.bind(this)],
|
|
1143
|
+
['LazyForEach.create', this.forEachCreationParser.bind(this)],
|
|
1144
|
+
['Repeat.create', this.repeatCreationParser.bind(this)],
|
|
1145
|
+
['View.create', this.viewComponentCreationParser.bind(this)],
|
|
1146
|
+
['If.branch', this.ifBranchCreationParser.bind(this)],
|
|
1147
|
+
['WaterFlow.create', this.waterFlowCreationParser.bind(this)],
|
|
1148
|
+
]);
|
|
1149
|
+
}
|
|
1150
|
+
return this._createParsers;
|
|
1151
|
+
}
|
|
1152
|
+
get COMPONENT_BEHAVIOR_PARSERS() {
|
|
1153
|
+
if (!this._behaviorParsers) {
|
|
1154
|
+
this._behaviorParsers = new Map([
|
|
1155
|
+
['tabBar', this.tabBarComponentParser.bind(this)],
|
|
1156
|
+
['navDestination', this.navDestinationComponentParser.bind(this)],
|
|
1157
|
+
['bindContextMenu', this.bindContextMenuComponentParser.bind(this)],
|
|
1158
|
+
['bindMenu', this.bindContextMenuComponentParser.bind(this)],
|
|
1159
|
+
['bindContentCover', this.bindContentCoverComponentParser.bind(this)],
|
|
1160
|
+
['bindSheet', this.bindContentCoverComponentParser.bind(this)],
|
|
1161
|
+
['bindPopup', this.bindPopupComponentParser.bind(this)],
|
|
1162
|
+
]);
|
|
1163
|
+
}
|
|
1164
|
+
return this._behaviorParsers;
|
|
1165
|
+
}
|
|
983
1166
|
componentCreateParse(local2Node, componentName, methodName, stmt, expr) {
|
|
984
1167
|
let parserFn = this.COMPONENT_CREATE_PARSERS.get(`${componentName}.${methodName}`);
|
|
985
1168
|
if (parserFn) {
|
|
@@ -1021,9 +1204,10 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
1021
1204
|
}
|
|
1022
1205
|
/**
|
|
1023
1206
|
* $temp4.margin({ top: 20 });
|
|
1024
|
-
* @param viewTree
|
|
1025
1207
|
* @param local2Node
|
|
1208
|
+
* @param stmt
|
|
1026
1209
|
* @param expr
|
|
1210
|
+
* @param shouldPush
|
|
1027
1211
|
*/
|
|
1028
1212
|
parseInstanceInvokeExpr(local2Node, stmt, expr, shouldPush = true) {
|
|
1029
1213
|
let temp = expr.getBase();
|
|
@@ -1266,7 +1450,7 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
1266
1450
|
if (!field) {
|
|
1267
1451
|
return undefined;
|
|
1268
1452
|
}
|
|
1269
|
-
const map =
|
|
1453
|
+
const map = StateValuesUtils.getCachedObjectLiteral(cls, this.getDeclaringArkClass().getDeclaringArkFile().getScene());
|
|
1270
1454
|
const builderValue = map.get(field);
|
|
1271
1455
|
if (!(builderValue instanceof Ref_1.ArkInstanceFieldRef)) {
|
|
1272
1456
|
return undefined;
|
|
@@ -1285,6 +1469,7 @@ class ViewTreeImpl extends TreeNodeStack {
|
|
|
1285
1469
|
}
|
|
1286
1470
|
}
|
|
1287
1471
|
exports.ViewTreeImpl = ViewTreeImpl;
|
|
1472
|
+
ViewTreeImpl.buildingTrees = new Set();
|
|
1288
1473
|
function buildViewTree(render) {
|
|
1289
1474
|
return new ViewTreeImpl(render);
|
|
1290
1475
|
}
|
|
@@ -8,20 +8,17 @@ export type ModuleID = number;
|
|
|
8
8
|
/**
|
|
9
9
|
* Lifecycle state of an {@link ArkModule}. Stored in the low 3 bits of {@link ArkModule.tags}.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Progression: NOT_LOADED → INDEX → SIGNATURES → BODIES.
|
|
12
|
+
* INDEX is downgrade-only (hollow export-reachable IR); never a direct loadModule target.
|
|
13
13
|
*/
|
|
14
14
|
export declare enum ModuleLoadState {
|
|
15
|
-
/** No data loaded yet. */
|
|
16
15
|
NOT_LOADED = 0,
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
/** IMPORTS + ArkFile content excluding method bodies (namespaces, classes, signatures). */
|
|
22
|
-
SIGNATURES = 3,
|
|
16
|
+
/** Hollow export-reachable ArkFile IR (bodies/AST stripped, non-exports pruned). */
|
|
17
|
+
INDEX = 1,
|
|
18
|
+
/** Classes/method signatures without method bodies. */
|
|
19
|
+
SIGNATURES = 2,
|
|
23
20
|
/** SIGNATURES + method bodies (ArkBody, CFG, Stmt/Expr). */
|
|
24
|
-
BODIES =
|
|
21
|
+
BODIES = 3
|
|
25
22
|
}
|
|
26
23
|
/**
|
|
27
24
|
* Category of an {@link ArkModule}. Stored in bits 3-4 of {@link ArkModule.tags}.
|
|
@@ -63,8 +60,8 @@ export declare class ArkModule {
|
|
|
63
60
|
*/
|
|
64
61
|
private unresolvedDependencies;
|
|
65
62
|
/**
|
|
66
|
-
* Intra-module file dependency graph, built during
|
|
67
|
-
*
|
|
63
|
+
* Intra-module file dependency graph, built during import/export analysis on the
|
|
64
|
+
* way to SIGNATURES. Undefined until {@link analyzeFileDependencies} has run.
|
|
68
65
|
*/
|
|
69
66
|
private fileDepGraph?;
|
|
70
67
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArkModule.d.ts","sourceRoot":"","sources":["../../../src/core/model/ArkModule.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;;;GAKG;AACH,oBAAY,eAAe;IACvB,
|
|
1
|
+
{"version":3,"file":"ArkModule.d.ts","sourceRoot":"","sources":["../../../src/core/model/ArkModule.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;;;GAKG;AACH,oBAAY,eAAe;IACvB,UAAU,IAAI;IACd,oFAAoF;IACpF,KAAK,IAAI;IACT,uDAAuD;IACvD,UAAU,IAAI;IACd,4DAA4D;IAC5D,MAAM,IAAI;CACb;AAED;;GAEG;AACH,oBAAY,UAAU;IAClB,gEAAgE;IAChE,OAAO,IAAI;IACX,kFAAkF;IAClF,GAAG,IAAI;IACP,sDAAsD;IACtD,UAAU,IAAI;CACjB;AAUD;;;;;;;;;GASG;AACH,qBAAa,SAAS;IAClB,wDAAwD;IACxD,OAAO,CAAC,UAAU,CAAc;IAChC,+EAA+E;IAC/E,OAAO,CAAC,UAAU,CAAc;IAEhC,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAmC;IAEnD;;;;OAIG;IACH,OAAO,CAAC,mBAAmB,CAAoC;IAE/D;;;OAGG;IACH,OAAO,CAAC,sBAAsB,CAAkC;IAEhE;;;OAGG;IACH,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC;;;OAGG;IACH,OAAO,CAAC,IAAI,CAAa;IAEzB,0CAA0C;IAC1C,OAAO,CAAC,KAAK,CAAQ;gBAET,KAAK,EAAE,KAAK;IAIxB,uDAAuD;IAChD,QAAQ,IAAI,KAAK;IAMxB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAMZ,aAAa,IAAI,MAAM;IAIvB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIvC,aAAa,IAAI,MAAM;IAIvB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIvC,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAInC,YAAY,IAAI,eAAe;IAI/B,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAI1C,aAAa,IAAI,UAAU;IAI3B,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAM5C;;;;OAIG;IACI,eAAe,IAAI,SAAS,EAAE;IAoBrC;;;;OAIG;IACI,aAAa,IAAI,SAAS,EAAE;IAsBnC;;;;OAIG;IACI,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/D;;OAEG;IACI,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI3D,sBAAsB,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;IAM/C,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3D,yBAAyB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAMvD,4EAA4E;IACrE,eAAe,IAAI,YAAY,GAAG,SAAS;IAI3C,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAI7D,yEAAyE;IAClE,gBAAgB,IAAI,OAAO;IAM3B,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI/B,aAAa,IAAI,IAAI;IAM5B;;;OAGG;IACI,YAAY,IAAI,MAAM;IAI7B;;;OAGG;IACI,gBAAgB,IAAI;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE;CAOtD"}
|
|
@@ -24,21 +24,18 @@ const json5parser_1 = require("../../utils/json5parser");
|
|
|
24
24
|
/**
|
|
25
25
|
* Lifecycle state of an {@link ArkModule}. Stored in the low 3 bits of {@link ArkModule.tags}.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* Progression: NOT_LOADED → INDEX → SIGNATURES → BODIES.
|
|
28
|
+
* INDEX is downgrade-only (hollow export-reachable IR); never a direct loadModule target.
|
|
29
29
|
*/
|
|
30
30
|
var ModuleLoadState;
|
|
31
31
|
(function (ModuleLoadState) {
|
|
32
|
-
/** No data loaded yet. */
|
|
33
32
|
ModuleLoadState[ModuleLoadState["NOT_LOADED"] = 0] = "NOT_LOADED";
|
|
34
|
-
/**
|
|
35
|
-
ModuleLoadState[ModuleLoadState["
|
|
36
|
-
/**
|
|
37
|
-
ModuleLoadState[ModuleLoadState["
|
|
38
|
-
/** IMPORTS + ArkFile content excluding method bodies (namespaces, classes, signatures). */
|
|
39
|
-
ModuleLoadState[ModuleLoadState["SIGNATURES"] = 3] = "SIGNATURES";
|
|
33
|
+
/** Hollow export-reachable ArkFile IR (bodies/AST stripped, non-exports pruned). */
|
|
34
|
+
ModuleLoadState[ModuleLoadState["INDEX"] = 1] = "INDEX";
|
|
35
|
+
/** Classes/method signatures without method bodies. */
|
|
36
|
+
ModuleLoadState[ModuleLoadState["SIGNATURES"] = 2] = "SIGNATURES";
|
|
40
37
|
/** SIGNATURES + method bodies (ArkBody, CFG, Stmt/Expr). */
|
|
41
|
-
ModuleLoadState[ModuleLoadState["BODIES"] =
|
|
38
|
+
ModuleLoadState[ModuleLoadState["BODIES"] = 3] = "BODIES";
|
|
42
39
|
})(ModuleLoadState = exports.ModuleLoadState || (exports.ModuleLoadState = {}));
|
|
43
40
|
/**
|
|
44
41
|
* Category of an {@link ArkModule}. Stored in bits 3-4 of {@link ArkModule.tags}.
|