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

javascript-obfuscator / javascript-obfuscator / 28996609307

09 Jul 2026 05:35AM UTC coverage: 96.31% (-0.01%) from 96.32%
28996609307

push

github

sanex3339
Update changelog

1978 of 2153 branches covered (91.87%)

Branch coverage included in aggregate %.

6034 of 6166 relevant lines covered (97.86%)

30483532.08 hits per line

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

88.76
/src/node-transformers/NodeTransformersRunner.ts
1
import { inject, injectable } from 'inversify';
6✔
2

3
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
6✔
4

5
import * as estraverse from '@javascript-obfuscator/estraverse';
6✔
6
import * as ESTree from 'estree';
7

8
import { TNodeTransformerFactory } from '../types/container/node-transformers/TNodeTransformerFactory';
9
import { TDictionary } from '../types/TDictionary';
10
import { TVisitorDirection } from '../types/node-transformers/TVisitorDirection';
11
import { TVisitorFunction } from '../types/node-transformers/TVisitorFunction';
12
import { TVisitorResult } from '../types/node-transformers/TVisitorResult';
13

14
import { INodeTransformer } from '../interfaces/node-transformers/INodeTransformer';
15
import { INodeTransformersRunner } from '../interfaces/node-transformers/INodeTransformersRunner';
16
import { ITransformerNamesGroupsBuilder } from '../interfaces/utils/ITransformerNamesGroupsBuilder';
17
import { IVisitor } from '../interfaces/node-transformers/IVisitor';
18

19
import { NodeTransformer } from '../enums/node-transformers/NodeTransformer';
20
import { NodeTransformationStage } from '../enums/node-transformers/NodeTransformationStage';
21
import { VisitorDirection } from '../enums/node-transformers/VisitorDirection';
6✔
22

23
import { NodeGuards } from '../node/NodeGuards';
6✔
24
import { NodeMetadata } from '../node/NodeMetadata';
6✔
25

26
interface IVisitorsData {
27
    enterVisitors: IVisitor[];
28
    leaveVisitors: IVisitor[];
29
    runOnProgramNodeOnly: boolean;
30
}
31

32
@injectable()
33
export class NodeTransformersRunner implements INodeTransformersRunner {
6✔
34
    /**
35
     * @type {TNodeTransformerFactory}
36
     */
37
    private readonly nodeTransformerFactory: TNodeTransformerFactory;
38

39
    /**
40
     * @type {ITransformerNamesGroupsBuilder}
41
     */
42
    private readonly nodeTransformerNamesGroupsBuilder: ITransformerNamesGroupsBuilder<
43
        NodeTransformer,
44
        INodeTransformer
45
    >;
46

47
    /**
48
     * @param {TNodeTransformerFactory} nodeTransformerFactory
49
     * @param {ITransformerNamesGroupsBuilder} nodeTransformerNamesGroupsBuilder
50
     */
51
    public constructor(
52
        @inject(ServiceIdentifiers.Factory__INodeTransformer)
53
        nodeTransformerFactory: TNodeTransformerFactory,
54
        @inject(ServiceIdentifiers.INodeTransformerNamesGroupsBuilder)
55
        nodeTransformerNamesGroupsBuilder: ITransformerNamesGroupsBuilder<NodeTransformer, INodeTransformer>
56
    ) {
57
        this.nodeTransformerFactory = nodeTransformerFactory;
201,758✔
58
        this.nodeTransformerNamesGroupsBuilder = nodeTransformerNamesGroupsBuilder;
201,758✔
59
    }
60

61
    /**
62
     * @param {T} astTree
63
     * @param {NodeTransformer[]} nodeTransformerNames
64
     * @param {NodeTransformationStage} nodeTransformationStage
65
     * @returns {T}
66
     */
67
    public transform<T extends ESTree.Node = ESTree.Program>(
68
        astTree: T,
69
        nodeTransformerNames: NodeTransformer[],
70
        nodeTransformationStage: NodeTransformationStage
71
    ): T {
72
        if (!nodeTransformerNames.length) {
1,673,511!
73
            return astTree;
×
74
        }
75

76
        const normalizedNodeTransformers: TDictionary<INodeTransformer> = this.buildNormalizedNodeTransformers(
1,673,511✔
77
            nodeTransformerNames,
78
            nodeTransformationStage
79
        );
80
        const nodeTransformerNamesGroups: NodeTransformer[][] =
81
            this.nodeTransformerNamesGroupsBuilder.build(normalizedNodeTransformers);
1,673,511✔
82

83
        for (const nodeTransformerNamesGroup of nodeTransformerNamesGroups) {
1,673,511✔
84
            const visitorsData: IVisitorsData = this.buildVisitorsData(
3,226,287✔
85
                nodeTransformerNamesGroup,
86
                normalizedNodeTransformers,
87
                nodeTransformationStage
88
            );
89
            const { enterVisitors, leaveVisitors } = visitorsData;
3,226,287✔
90

91
            if (!enterVisitors.length && !leaveVisitors.length) {
3,226,287!
92
                continue;
×
93
            }
94

95
            if (this.canRunOnProgramNodeOnly(visitorsData, astTree)) {
3,226,287✔
96
                astTree = this.runOnProgramNodeOnly(astTree, enterVisitors);
422,086✔
97

98
                continue;
422,086✔
99
            }
100

101
            estraverse.replace(astTree, {
2,804,201✔
102
                enter: this.mergeVisitorsForDirection(enterVisitors, VisitorDirection.Enter),
103
                leave: this.mergeVisitorsForDirection(leaveVisitors, VisitorDirection.Leave)
104
            });
105
        }
106

107
        return astTree;
1,673,505✔
108
    }
109

110
    /**
111
     * @param {NodeTransformer[]} nodeTransformerNamesGroup
112
     * @param {TDictionary<INodeTransformer>} normalizedNodeTransformers
113
     * @param {NodeTransformationStage} nodeTransformationStage
114
     * @returns {IVisitorsData}
115
     */
116
    private buildVisitorsData(
117
        nodeTransformerNamesGroup: NodeTransformer[],
118
        normalizedNodeTransformers: TDictionary<INodeTransformer>,
119
        nodeTransformationStage: NodeTransformationStage
120
    ): IVisitorsData {
121
        const enterVisitors: IVisitor[] = [];
3,226,287✔
122
        const leaveVisitors: IVisitor[] = [];
3,226,287✔
123
        let runOnProgramNodeOnly: boolean = true;
3,226,287✔
124

125
        for (const nodeTransformerName of nodeTransformerNamesGroup) {
3,226,287✔
126
            const nodeTransformer: INodeTransformer = normalizedNodeTransformers[nodeTransformerName];
7,573,017✔
127
            const visitor: IVisitor | null = nodeTransformer.getVisitor(nodeTransformationStage);
7,573,017✔
128

129
            if (!visitor) {
7,573,017!
130
                continue;
×
131
            }
132

133
            if (!nodeTransformer.runOnProgramNodeOnly) {
7,573,017✔
134
                runOnProgramNodeOnly = false;
6,485,586✔
135
            }
136

137
            if (visitor.enter) {
7,573,017✔
138
                enterVisitors.push({ enter: visitor.enter });
5,358,093✔
139
            }
140

141
            if (visitor.leave) {
7,573,017✔
142
                leaveVisitors.push({ leave: visitor.leave });
2,255,140✔
143
            }
144
        }
145

146
        return { enterVisitors, leaveVisitors, runOnProgramNodeOnly };
3,226,287✔
147
    }
148

149
    /**
150
     * @param {IVisitorsData} visitorsData
151
     * @param {Node} astTree
152
     * @returns {boolean}
153
     */
154
    private canRunOnProgramNodeOnly(visitorsData: IVisitorsData, astTree: ESTree.Node): boolean {
155
        return (
3,226,287✔
156
            visitorsData.runOnProgramNodeOnly &&
4,070,459✔
157
            !visitorsData.leaveVisitors.length &&
158
            NodeGuards.isProgramNode(astTree)
159
        );
160
    }
161

162
    /**
163
     * @param {T} astTree
164
     * @param {IVisitor[]} enterVisitors
165
     * @returns {T}
166
     */
167
    private runOnProgramNodeOnly<T extends ESTree.Node>(astTree: T, enterVisitors: IVisitor[]): T {
168
        const visitorResult: TVisitorResult = this.mergeVisitorsForDirection(
422,086✔
169
            enterVisitors,
170
            VisitorDirection.Enter
171
        )(astTree, astTree.parentNode ?? null);
1,266,258!
172

173
        return visitorResult && NodeGuards.isNode(visitorResult) ? <T>visitorResult : astTree;
422,086!
174
    }
175

176
    /**
177
     * @param {NodeTransformer[]} nodeTransformerNames
178
     * @param {NodeTransformationStage} nodeTransformationStage
179
     * @returns {TDictionary<INodeTransformer>}
180
     */
181
    private buildNormalizedNodeTransformers(
182
        nodeTransformerNames: NodeTransformer[],
183
        nodeTransformationStage: NodeTransformationStage
184
    ): TDictionary<INodeTransformer> {
185
        return nodeTransformerNames.reduce<TDictionary<INodeTransformer>>(
1,673,511✔
186
            (acc: TDictionary<INodeTransformer>, nodeTransformerName: NodeTransformer) => {
187
                const nodeTransformer: INodeTransformer = this.nodeTransformerFactory(nodeTransformerName);
51,506,901✔
188

189
                if (!nodeTransformer.getVisitor(nodeTransformationStage)) {
51,506,901✔
190
                    return acc;
43,933,878✔
191
                }
192

193
                return <TDictionary<INodeTransformer>>{
7,573,023✔
194
                    ...acc,
195
                    [nodeTransformerName]: nodeTransformer
196
                };
197
            },
198
            {}
199
        );
200
    }
201

202
    /**
203
     * @param {IVisitor[]} visitors
204
     * @param {TVisitorDirection} direction
205
     * @returns {TVisitorFunction}
206
     */
207
    private mergeVisitorsForDirection(visitors: IVisitor[], direction: TVisitorDirection): TVisitorFunction {
208
        const visitorsLength: number = visitors.length;
6,030,488✔
209

210
        if (!visitorsLength) {
6,030,488✔
211
            return (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node => node;
2,097,644,454✔
212
        }
213

214
        return (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | estraverse.VisitorOption => {
3,945,305✔
215
            if (NodeMetadata.isIgnoredNode(node)) {
2,673,322,485✔
216
                return estraverse.VisitorOption.Skip;
563,994✔
217
            }
218

219
            for (let i: number = 0; i < visitorsLength; i++) {
2,672,758,491✔
220
                const visitorFunction: TVisitorFunction | undefined = visitors[i][direction];
5,070,507,911✔
221

222
                if (!visitorFunction) {
5,070,507,911!
223
                    continue;
×
224
                }
225

226
                const visitorResult: TVisitorResult = visitorFunction(node, parentNode);
5,070,507,911✔
227
                const isValidVisitorResult = visitorResult && NodeGuards.isNode(visitorResult);
5,070,507,905✔
228

229
                if (!isValidVisitorResult) {
5,070,507,905✔
230
                    continue;
3,522,514,103✔
231
                }
232

233
                node = visitorResult;
1,547,993,802✔
234
            }
235

236
            return node;
2,672,758,485✔
237
        };
238
    }
239
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc