arkanalyzer 1.0.91 → 1.0.92

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.
@@ -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
- function backtraceLocalInitValue(value) {
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
- return backtraceLocalInitValue(rightOp.getBase());
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 ((objectLiteralCls === null || objectLiteralCls === void 0 ? void 0 : objectLiteralCls.getCategory()) !== ArkClass_1.ClassCategory.OBJECT) {
80
+ if (!objectLiteralCls || objectLiteralCls.getCategory() !== ArkClass_1.ClassCategory.OBJECT) {
72
81
  return map;
73
82
  }
74
- objectLiteralCls === null || objectLiteralCls === void 0 ? void 0 : objectLiteralCls.getFields().forEach(field => {
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
- return new StateValuesUtils(declaringArkClass);
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, visitor = new Set()) {
106
- if (visitor.has(stmt)) {
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
- visitor.add(stmt);
110
- let values = stmt.getUses();
111
- if (stmt instanceof Stmt_1.ArkAssignStmt) {
112
- values.push(stmt.getLeftOp());
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
- for (const v of values) {
115
- this.parseValueUsesStateValues(v, uses, wholeMethod, visitor);
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 = parseObjectLiteral(cls, this.declaringArkClass.getDeclaringArkFile().getScene());
210
+ let map = this.getObjectLiteralMap(cls);
149
211
  this.objectLiteralMapUsedStateValues(uses, map);
150
212
  return uses;
151
213
  }
152
- parseMethodUsesStateValues(methodSignature, uses, visitor = new Set()) {
153
- var _a;
154
- if (visitor.has(methodSignature)) {
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
- visitor.add(methodSignature);
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, uses, true, visitor);
264
+ this.parseStmtUsesStateValues(stmt, targetUses, true);
168
265
  }
169
266
  }
170
- parseValueUsesStateValues(v, uses = new Set(), wholeMethod = false, visitor = new Set()) {
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, visitor);
180
- this.parseValueUsesStateValues(v.getIndex(), uses, wholeMethod, visitor);
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, visitor);
280
+ this.parseValueUsesStateValues(v.getBase(), uses, wholeMethod);
184
281
  for (const arg of v.getArgs()) {
185
- this.parseValueUsesStateValues(arg, uses, wholeMethod, visitor);
282
+ this.parseValueUsesStateValues(arg, uses, wholeMethod);
186
283
  }
187
- this.parseMethodUsesStateValues(v.getMethodSignature(), uses, visitor);
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, visitor);
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, visitor);
292
+ this.parseValueUsesStateValues(v.getFuncPtrLocal(), uses, wholeMethod);
196
293
  for (const arg of v.getArgs()) {
197
- this.parseValueUsesStateValues(arg, uses, wholeMethod, visitor);
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, visitor);
202
- this.parseValueUsesStateValues(v.getOp2(), uses, wholeMethod, visitor);
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
- if (v.getName() === 'this') {
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 (tree.COMPONENT_BEHAVIOR_PARSERS.has(key) && expr instanceof Expr_1.ArkInstanceInvokeExpr) {
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.COMPONENT_CREATE_PARSERS = new Map([
517
- ['ForEach.create', this.forEachCreationParser.bind(this)],
518
- ['LazyForEach.create', this.forEachCreationParser.bind(this)],
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
- this.loadClasssFieldTypes();
679
+ let sig;
575
680
  if (this.render.hasBuilderDecorator()) {
576
- let node = ViewTreeNodeImpl.createBuilderNode();
577
- node.signature = this.render.getSignature();
578
- node.classSignature = node.signature;
579
- this.push(node);
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
- if (this.render.getCfg()) {
582
- this.buildViewTreeFromCfg(this.render.getCfg());
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
- if (!this.stateValues.has(field)) {
596
- this.stateValues.set(field, new Set());
721
+ let nodes = this.stateValues.get(field);
722
+ if (!nodes) {
723
+ nodes = new Set();
724
+ this.stateValues.set(field, nodes);
597
725
  }
598
- let sets = this.stateValues.get(field);
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 (root.hasBuilderParam()) {
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().forEach(value => {
883
- if (value instanceof Stmt_1.ArkAssignStmt && value.getRightOp() instanceof Expr_1.ArkInstanceInvokeExpr) {
884
- const rightOp = value.getRightOp();
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
- else {
920
- logger.error(`ViewTree->viewComponentCreationParser not found class ${clsSignature.toString()}. ${stmt.toString()}`);
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 = parseObjectLiteral(cls, this.getDeclaringArkClass().getDeclaringArkFile().getScene());
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
- * The states form an incremental progression: each state is a superset of the previous one,
12
- * matching the {@link ModuleDepthLevel} data depth levels.
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
- /** Module metadata + dependency topology + ArkFile path-only basic info. */
18
- META = 1,
19
- /** META + export/import info for all ArkFiles + intra-module file dependencies. */
20
- IMPORTS = 2,
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 = 4
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 file dependency analysis
67
- * (IMPORTS level). Undefined until {@link analyzeFileDependencies} has run.
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,0BAA0B;IAC1B,UAAU,IAAI;IACd,4EAA4E;IAC5E,IAAI,IAAI;IACR,mFAAmF;IACnF,OAAO,IAAI;IACX,2FAA2F;IAC3F,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"}
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
- * The states form an incremental progression: each state is a superset of the previous one,
28
- * matching the {@link ModuleDepthLevel} data depth levels.
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
- /** Module metadata + dependency topology + ArkFile path-only basic info. */
35
- ModuleLoadState[ModuleLoadState["META"] = 1] = "META";
36
- /** META + export/import info for all ArkFiles + intra-module file dependencies. */
37
- ModuleLoadState[ModuleLoadState["IMPORTS"] = 2] = "IMPORTS";
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"] = 4] = "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}.