• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { ArkInstanceInvokeExpr } from '../../core/base/Expr';
17import { Local } from '../../core/base/Local';
18import { Stmt, ArkInvokeStmt } from '../../core/base/Stmt';
19import { ArkMethod } from '../../core/model/ArkMethod';
20import { ClassSignature } from '../../core/model/ArkSignature';
21import { Scene } from '../../Scene';
22import { COMPONENT_LIFECYCLE_METHOD_NAME } from '../../utils/entryMethodUtils';
23import Logger, { LOG_MODULE_TYPE } from '../../utils/logger';
24
25const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'Dummy Call');
26
27/**
28 * TODO: constructor pointer and cid
29 */
30export class DummyCallCreator {
31    private scene: Scene;
32    private pageMap;
33    // TODO: classSig -> str ?
34    private componentMap: Map<ClassSignature, Set<Stmt>>;
35
36    constructor(scene: Scene) {
37        this.scene = scene;
38        this.componentMap = new Map();
39        this.pageMap = new Map();
40    }
41
42    public getDummyCallByPage(classSig: ClassSignature, basePage: Local): Set<Stmt> {
43        let dummyCallStmts = this.pageMap.get(classSig);
44        if (dummyCallStmts) {
45            return dummyCallStmts;
46        }
47
48        dummyCallStmts = this.buildDummyCallBody(classSig, basePage);
49
50        this.pageMap.set(classSig, dummyCallStmts);
51        return dummyCallStmts;
52    }
53
54    public getDummyCallByComponent(classSig: ClassSignature, baseComponent: Local): Set<Stmt> {
55        let dummyCallStmts = this.componentMap.get(classSig);
56        if (dummyCallStmts) {
57            return dummyCallStmts;
58        }
59
60        dummyCallStmts = this.buildDummyCallBody(classSig, baseComponent);
61
62        this.componentMap.set(classSig, dummyCallStmts);
63        return dummyCallStmts;
64    }
65
66    /**
67     * build dummy call edge with class signature, including a class new expr and call back function invokes
68     * @param classSig class signature
69     * @returns dummy call edges
70     */
71    private buildDummyCallBody(classSig: ClassSignature, baseComponent: Local): Set<Stmt> {
72        let dummyCallStmts: Set<Stmt> = new Set();
73
74        this.getComponentCallStmts(classSig, baseComponent).forEach(stmt => dummyCallStmts.add(stmt));
75
76        return dummyCallStmts;
77    }
78
79    private getComponentCallStmts(classSig: ClassSignature, base: Local): Stmt[] {
80        let componentClass = this.scene.getClass(classSig);
81        if (!componentClass) {
82            logger.error(`can not find class ${classSig.toString()}`);
83            return [];
84        }
85
86        let callStmts: Stmt[] = [];
87        // filter callback method
88        componentClass
89            .getMethods()
90            .filter(method => COMPONENT_LIFECYCLE_METHOD_NAME.includes(method.getName()))
91            .forEach((method: ArkMethod) => {
92                // TODO: args pointer ?
93                if (method.getParameters().length === 0) {
94                    callStmts.push(new ArkInvokeStmt(new ArkInstanceInvokeExpr(base, method.getSignature(), [])));
95                } else {
96                    logger.warn(`parameters in callback function hasn't been processed: ${method.getSignature().toString()}`);
97                }
98            });
99
100        return callStmts;
101    }
102}
103