• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

javascript-obfuscator / javascript-obfuscator / 19907815758

03 Dec 2025 08:27PM UTC coverage: 97.319%. Remained the same
19907815758

push

github

sanex3339
Adjust precommit hook

1770 of 1891 branches covered (93.6%)

Branch coverage included in aggregate %.

5671 of 5755 relevant lines covered (98.54%)

34102965.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.25
/src/node-transformers/string-array-transformers/StringArrayScopeCallsWrapperTransformer.ts
1
import { inject, injectable } from 'inversify';
6✔
2
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
6✔
3

4
import * as ESTree from 'estree';
5

6
import { TInitialData } from '../../types/TInitialData';
7
import { TNodeWithLexicalScopeStatements } from '../../types/node/TNodeWithLexicalScopeStatements';
8
import { TStatement } from '../../types/node/TStatement';
9
import { TStringArrayScopeCallsWrappersDataByEncoding } from '../../types/node-transformers/string-array-transformers/TStringArrayScopeCallsWrappersDataByEncoding';
10
import { TStringArrayCustomNodeFactory } from '../../types/container/custom-nodes/TStringArrayCustomNodeFactory';
11

12
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
13
import { IOptions } from '../../interfaces/options/IOptions';
14
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
15
import { IStringArrayScopeCallsWrapperData } from '../../interfaces/node-transformers/string-array-transformers/IStringArrayScopeCallsWrapperData';
16
import { IStringArrayScopeCallsWrappersData } from '../../interfaces/node-transformers/string-array-transformers/IStringArrayScopeCallsWrappersData';
17
import { IStringArrayScopeCallsWrappersDataStorage } from '../../interfaces/storages/string-array-transformers/IStringArrayScopeCallsWrappersDataStorage';
18
import { IStringArrayStorage } from '../../interfaces/storages/string-array-transformers/IStringArrayStorage';
19
import { IVisitedLexicalScopeNodesStackStorage } from '../../interfaces/storages/string-array-transformers/IVisitedLexicalScopeNodesStackStorage';
20
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
21

22
import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
6✔
23
import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
6✔
24
import { StringArrayCustomNode } from '../../enums/custom-nodes/StringArrayCustomNode';
6✔
25
import { StringArrayWrappersType } from '../../enums/node-transformers/string-array-transformers/StringArrayWrappersType';
6✔
26

27
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
6✔
28
import { NodeAppender } from '../../node/NodeAppender';
6✔
29
import { NodeGuards } from '../../node/NodeGuards';
6✔
30
import { StringArrayScopeCallsWrapperFunctionNode } from '../../custom-nodes/string-array-nodes/StringArrayScopeCallsWrapperFunctionNode';
31
import { StringArrayScopeCallsWrapperVariableNode } from '../../custom-nodes/string-array-nodes/StringArrayScopeCallsWrapperVariableNode';
32

33
@injectable()
34
export class StringArrayScopeCallsWrapperTransformer extends AbstractNodeTransformer {
6✔
35
    /**
36
     * @type {NodeTransformer[]}
37
     */
38
    public override readonly runAfter: NodeTransformer[] = [NodeTransformer.StringArrayRotateFunctionTransformer];
197,808✔
39

40
    /**
41
     * @type {IStringArrayStorage}
42
     */
43
    private readonly stringArrayStorage: IStringArrayStorage;
44

45
    /**
46
     * @type {IStringArrayScopeCallsWrappersDataStorage}
47
     */
48
    private readonly stringArrayScopeCallsWrappersDataStorage: IStringArrayScopeCallsWrappersDataStorage;
49

50
    /**
51
     * @type {TStringArrayCustomNodeFactory}
52
     */
53
    private readonly stringArrayTransformerCustomNodeFactory: TStringArrayCustomNodeFactory;
54

55
    /**
56
     * @type {IVisitedLexicalScopeNodesStackStorage}
57
     */
58
    private readonly visitedLexicalScopeNodesStackStorage: IVisitedLexicalScopeNodesStackStorage;
59

60
    /**
61
     * @param {IRandomGenerator} randomGenerator
62
     * @param {IOptions} options
63
     * @param {IVisitedLexicalScopeNodesStackStorage} visitedLexicalScopeNodesStackStorage
64
     * @param {IStringArrayStorage} stringArrayStorage
65
     * @param {IStringArrayScopeCallsWrappersDataStorage} stringArrayScopeCallsWrappersDataStorage
66
     * @param {TStringArrayCustomNodeFactory} stringArrayTransformerCustomNodeFactory
67
     */
68
    public constructor(
69
        @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
70
        @inject(ServiceIdentifiers.IOptions) options: IOptions,
71
        @inject(ServiceIdentifiers.IVisitedLexicalScopeNodesStackStorage)
72
        visitedLexicalScopeNodesStackStorage: IVisitedLexicalScopeNodesStackStorage,
73
        @inject(ServiceIdentifiers.IStringArrayStorage) stringArrayStorage: IStringArrayStorage,
74
        @inject(ServiceIdentifiers.IStringArrayScopeCallsWrappersDataStorage)
75
        stringArrayScopeCallsWrappersDataStorage: IStringArrayScopeCallsWrappersDataStorage,
76
        @inject(ServiceIdentifiers.Factory__IStringArrayCustomNode)
77
        stringArrayTransformerCustomNodeFactory: TStringArrayCustomNodeFactory
78
    ) {
79
        super(randomGenerator, options);
197,808✔
80

81
        this.visitedLexicalScopeNodesStackStorage = visitedLexicalScopeNodesStackStorage;
197,808✔
82
        this.stringArrayStorage = stringArrayStorage;
197,808✔
83
        this.stringArrayScopeCallsWrappersDataStorage = stringArrayScopeCallsWrappersDataStorage;
197,808✔
84
        this.stringArrayTransformerCustomNodeFactory = stringArrayTransformerCustomNodeFactory;
197,808✔
85
    }
86

87
    /**
88
     * @param {NodeTransformationStage} nodeTransformationStage
89
     * @returns {IVisitor | null}
90
     */
91
    public getVisitor(nodeTransformationStage: NodeTransformationStage): IVisitor | null {
92
        if (!this.options.stringArrayWrappersCount) {
1,442,388✔
93
            return null;
1,215,120✔
94
        }
95

96
        switch (nodeTransformationStage) {
227,268✔
97
            case NodeTransformationStage.StringArray:
227,268✔
98
                return {
54,708✔
99
                    enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
100
                        if (parentNode && NodeGuards.isNodeWithLexicalScopeStatements(node, parentNode)) {
94,295,137✔
101
                            this.onLexicalScopeNodeEnter(node);
718,853✔
102
                        }
103
                    },
104
                    leave: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
105
                        if (parentNode && NodeGuards.isNodeWithLexicalScopeStatements(node, parentNode)) {
94,295,137✔
106
                            this.onLexicalScopeNodeLeave();
718,853✔
107

108
                            return this.transformNode(node);
718,853✔
109
                        }
110
                    }
111
                };
112

113
            default:
114
                return null;
172,560✔
115
        }
116
    }
117

118
    /**
119
     * @param {TNodeWithLexicalScopeStatements} lexicalScopeBodyNode
120
     * @returns {TNodeWithLexicalScopeStatements}
121
     */
122
    public transformNode(lexicalScopeBodyNode: TNodeWithLexicalScopeStatements): TNodeWithLexicalScopeStatements {
123
        const stringArrayScopeCallsWrappersDataByEncoding: TStringArrayScopeCallsWrappersDataByEncoding | null =
124
            this.stringArrayScopeCallsWrappersDataStorage.get(lexicalScopeBodyNode) ?? null;
718,853✔
125

126
        if (!stringArrayScopeCallsWrappersDataByEncoding) {
718,853✔
127
            return lexicalScopeBodyNode;
273,441✔
128
        }
129

130
        const stringArrayScopeCallsWrappersDataList: (IStringArrayScopeCallsWrappersData | undefined)[] = Object.values(
445,412✔
131
            stringArrayScopeCallsWrappersDataByEncoding
132
        );
133

134
        // iterates over data for each encoding type
135
        for (const stringArrayScopeCallsWrappersData of stringArrayScopeCallsWrappersDataList) {
445,412✔
136
            if (!stringArrayScopeCallsWrappersData) {
641,056!
137
                continue;
×
138
            }
139

140
            const { scopeCallsWrappersData } = stringArrayScopeCallsWrappersData;
641,056✔
141
            const scopeCallsWrappersDataLength: number = scopeCallsWrappersData.length;
641,056✔
142

143
            /**
144
             * Iterates over each name of scope wrapper name
145
             * Reverse iteration appends wrappers at index `0` at the correct order
146
             */
147
            for (let i = scopeCallsWrappersDataLength - 1; i >= 0; i--) {
641,056✔
148
                const stringArrayScopeCallsWrapperData = scopeCallsWrappersData[i];
1,677,509✔
149
                const upperStringArrayCallsWrapperData = this.getUpperStringArrayCallsWrapperData(
1,677,509✔
150
                    stringArrayScopeCallsWrappersData
151
                );
152

153
                this.getAndAppendStringArrayScopeCallsWrapperNode(
1,677,509✔
154
                    lexicalScopeBodyNode,
155
                    stringArrayScopeCallsWrapperData,
156
                    upperStringArrayCallsWrapperData
157
                );
158
            }
159
        }
160

161
        return lexicalScopeBodyNode;
445,412✔
162
    }
163

164
    /**
165
     * @param {IStringArrayScopeCallsWrappersData} stringArrayScopeCallsWrappersData
166
     * @returns {IStringArrayScopeCallsWrapperData}
167
     */
168
    private getRootStringArrayCallsWrapperData(
169
        stringArrayScopeCallsWrappersData: IStringArrayScopeCallsWrappersData
170
    ): IStringArrayScopeCallsWrapperData {
171
        const { encoding } = stringArrayScopeCallsWrappersData;
1,677,509✔
172

173
        return {
1,677,509✔
174
            name: this.stringArrayStorage.getStorageCallsWrapperName(encoding),
175
            index: 0,
176
            parameterIndexesData: null
177
        };
178
    }
179

180
    /**
181
     * @param {IStringArrayScopeCallsWrappersData} stringArrayScopeCallsWrappersData
182
     * @returns {IStringArrayScopeCallsWrapperData}
183
     */
184
    private getUpperStringArrayCallsWrapperData(
185
        stringArrayScopeCallsWrappersData: IStringArrayScopeCallsWrappersData
186
    ): IStringArrayScopeCallsWrapperData {
187
        const { encoding } = stringArrayScopeCallsWrappersData;
1,677,509✔
188

189
        const rootStringArrayCallsWrapperData = this.getRootStringArrayCallsWrapperData(
1,677,509✔
190
            stringArrayScopeCallsWrappersData
191
        );
192

193
        if (!this.options.stringArrayWrappersChainedCalls) {
1,677,509✔
194
            return rootStringArrayCallsWrapperData;
12,525✔
195
        }
196

197
        const parentLexicalScopeBodyNode: TNodeWithLexicalScopeStatements | null =
198
            this.visitedLexicalScopeNodesStackStorage.getLastElement() ?? null;
1,664,984✔
199

200
        if (!parentLexicalScopeBodyNode) {
1,664,984✔
201
            return rootStringArrayCallsWrapperData;
14,482✔
202
        }
203

204
        const parentLexicalScopeCallsWrappersDataByEncoding: TStringArrayScopeCallsWrappersDataByEncoding | null =
205
            this.stringArrayScopeCallsWrappersDataStorage.get(parentLexicalScopeBodyNode) ?? null;
1,650,502✔
206
        const parentScopeCallsWrappersData: IStringArrayScopeCallsWrapperData[] | null =
207
            parentLexicalScopeCallsWrappersDataByEncoding?.[encoding]?.scopeCallsWrappersData ?? null;
1,650,502✔
208

209
        if (!parentScopeCallsWrappersData?.length) {
1,650,502✔
210
            return rootStringArrayCallsWrapperData;
168,377✔
211
        }
212

213
        return this.randomGenerator.getRandomGenerator().pickone(parentScopeCallsWrappersData);
1,482,125✔
214
    }
215

216
    /**
217
     * @param {TNodeWithLexicalScopeStatements} lexicalScopeBodyNode
218
     * @param {IStringArrayScopeCallsWrapperData} stringArrayScopeCallsWrapperData
219
     * @param {IStringArrayScopeCallsWrapperData} upperStringArrayCallsWrapperData
220
     */
221
    private getAndAppendStringArrayScopeCallsWrapperNode(
222
        lexicalScopeBodyNode: TNodeWithLexicalScopeStatements,
223
        stringArrayScopeCallsWrapperData: IStringArrayScopeCallsWrapperData,
224
        upperStringArrayCallsWrapperData: IStringArrayScopeCallsWrapperData
225
    ): void {
226
        let stringArrayScopeCallsWrapperNode: TStatement[];
227

228
        switch (this.options.stringArrayWrappersType) {
1,677,509✔
229
            case StringArrayWrappersType.Function: {
1,748,519✔
230
                const randomIndex: number = this.randomGenerator.getRandomInteger(
1,606,499✔
231
                    0,
232
                    lexicalScopeBodyNode.body.length - 1
233
                );
234

235
                stringArrayScopeCallsWrapperNode = this.getStringArrayScopeCallsWrapperFunctionNode(
1,606,499✔
236
                    stringArrayScopeCallsWrapperData,
237
                    upperStringArrayCallsWrapperData
238
                );
239

240
                NodeAppender.insertAtIndex(lexicalScopeBodyNode, stringArrayScopeCallsWrapperNode, randomIndex);
1,606,499✔
241

242
                break;
1,606,499✔
243
            }
244

245
            case StringArrayWrappersType.Variable:
246
            default: {
247
                stringArrayScopeCallsWrapperNode = this.getStringArrayScopeCallsWrapperVariableNode(
71,010✔
248
                    stringArrayScopeCallsWrapperData,
249
                    upperStringArrayCallsWrapperData
250
                );
251

252
                NodeAppender.prepend(lexicalScopeBodyNode, stringArrayScopeCallsWrapperNode);
71,010✔
253
            }
254
        }
255
    }
256

257
    /**
258
     * @param {IStringArrayScopeCallsWrapperData} stringArrayScopeCallsWrapperData
259
     * @param {IStringArrayScopeCallsWrapperData} upperStringArrayCallsWrapperData
260
     * @returns {TStatement[]}
261
     */
262
    private getStringArrayScopeCallsWrapperVariableNode(
263
        stringArrayScopeCallsWrapperData: IStringArrayScopeCallsWrapperData,
264
        upperStringArrayCallsWrapperData: IStringArrayScopeCallsWrapperData
265
    ): TStatement[] {
266
        const stringArrayScopeCallsWrapperVariableNode: ICustomNode<
267
            TInitialData<StringArrayScopeCallsWrapperVariableNode>
268
        > = this.stringArrayTransformerCustomNodeFactory(
71,010✔
269
            StringArrayCustomNode.StringArrayScopeCallsWrapperVariableNode
270
        );
271

272
        stringArrayScopeCallsWrapperVariableNode.initialize(
71,010✔
273
            stringArrayScopeCallsWrapperData,
274
            upperStringArrayCallsWrapperData
275
        );
276

277
        return stringArrayScopeCallsWrapperVariableNode.getNode();
71,010✔
278
    }
279

280
    /**
281
     * @param {IStringArrayScopeCallsWrapperData} stringArrayScopeCallsWrapperData
282
     * @param {IStringArrayScopeCallsWrapperData} upperStringArrayCallsWrapperData
283
     * @returns {TStatement[]}
284
     */
285
    private getStringArrayScopeCallsWrapperFunctionNode(
286
        stringArrayScopeCallsWrapperData: IStringArrayScopeCallsWrapperData,
287
        upperStringArrayCallsWrapperData: IStringArrayScopeCallsWrapperData
288
    ): TStatement[] {
289
        const stringArrayScopeCallsWrapperFunctionNode: ICustomNode<
290
            TInitialData<StringArrayScopeCallsWrapperFunctionNode>
291
        > = this.stringArrayTransformerCustomNodeFactory(
1,606,499✔
292
            StringArrayCustomNode.StringArrayScopeCallsWrapperFunctionNode
293
        );
294

295
        stringArrayScopeCallsWrapperFunctionNode.initialize(
1,606,499✔
296
            stringArrayScopeCallsWrapperData,
297
            upperStringArrayCallsWrapperData
298
        );
299

300
        return stringArrayScopeCallsWrapperFunctionNode.getNode();
1,606,499✔
301
    }
302

303
    /**
304
     * @param {TNodeWithLexicalScopeStatements} lexicalScopeBodyNode
305
     */
306
    private onLexicalScopeNodeEnter(lexicalScopeBodyNode: TNodeWithLexicalScopeStatements): void {
307
        this.visitedLexicalScopeNodesStackStorage.push(lexicalScopeBodyNode);
718,853✔
308
    }
309

310
    private onLexicalScopeNodeLeave(): void {
311
        this.visitedLexicalScopeNodesStackStorage.pop();
718,853✔
312
    }
313
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc