js-confuser 2.0.0-alpha.5 → 2.0.1

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.
Files changed (113) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +43 -43
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/workflows/node.js.yml +28 -28
  4. package/.prettierrc +4 -4
  5. package/CHANGELOG.md +1015 -989
  6. package/CODE_OF_CONDUCT.md +131 -131
  7. package/CONTRIBUTING.md +52 -52
  8. package/LICENSE +21 -21
  9. package/Migration.md +72 -71
  10. package/README.md +86 -78
  11. package/dist/constants.js +43 -43
  12. package/dist/index.js +14 -23
  13. package/dist/obfuscator.js +31 -25
  14. package/dist/order.js +4 -4
  15. package/dist/presets.js +31 -31
  16. package/dist/templates/integrityTemplate.js +4 -4
  17. package/dist/templates/template.js +1 -2
  18. package/dist/transforms/astScrambler.js +1 -2
  19. package/dist/transforms/calculator.js +1 -2
  20. package/dist/transforms/controlFlowFlattening.js +93 -63
  21. package/dist/transforms/deadCode.js +1 -2
  22. package/dist/transforms/dispatcher.js +4 -5
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +1 -2
  24. package/dist/transforms/extraction/objectExtraction.js +1 -2
  25. package/dist/transforms/finalizer.js +1 -2
  26. package/dist/transforms/flatten.js +1 -2
  27. package/dist/transforms/identifier/globalConcealing.js +15 -2
  28. package/dist/transforms/identifier/movedDeclarations.js +8 -7
  29. package/dist/transforms/identifier/renameVariables.js +7 -7
  30. package/dist/transforms/lock/integrity.js +11 -10
  31. package/dist/transforms/lock/lock.js +2 -3
  32. package/dist/transforms/minify.js +11 -29
  33. package/dist/transforms/opaquePredicates.js +1 -2
  34. package/dist/transforms/pack.js +5 -2
  35. package/dist/transforms/plugin.js +18 -19
  36. package/dist/transforms/preparation.js +16 -16
  37. package/dist/transforms/renameLabels.js +1 -2
  38. package/dist/transforms/rgf.js +8 -9
  39. package/dist/transforms/shuffle.js +1 -2
  40. package/dist/transforms/string/encoding.js +1 -2
  41. package/dist/transforms/string/stringCompression.js +3 -4
  42. package/dist/transforms/string/stringConcealing.js +8 -3
  43. package/dist/transforms/string/stringEncoding.js +1 -2
  44. package/dist/transforms/variableMasking.js +1 -2
  45. package/dist/utils/NameGen.js +2 -2
  46. package/dist/utils/PredicateGen.js +1 -2
  47. package/dist/utils/ast-utils.js +87 -88
  48. package/dist/utils/function-utils.js +8 -8
  49. package/dist/utils/node.js +5 -6
  50. package/dist/utils/object-utils.js +4 -4
  51. package/dist/utils/random-utils.js +20 -20
  52. package/dist/utils/static-utils.js +1 -2
  53. package/dist/validateOptions.js +4 -7
  54. package/index.d.ts +17 -17
  55. package/package.json +61 -59
  56. package/src/constants.ts +168 -168
  57. package/src/index.ts +118 -118
  58. package/src/obfuscationResult.ts +49 -49
  59. package/src/obfuscator.ts +501 -497
  60. package/src/options.ts +407 -407
  61. package/src/order.ts +54 -54
  62. package/src/presets.ts +125 -125
  63. package/src/templates/bufferToStringTemplate.ts +57 -57
  64. package/src/templates/deadCodeTemplates.ts +1185 -1185
  65. package/src/templates/getGlobalTemplate.ts +76 -76
  66. package/src/templates/integrityTemplate.ts +64 -64
  67. package/src/templates/setFunctionLengthTemplate.ts +11 -11
  68. package/src/templates/stringCompressionTemplate.ts +20 -20
  69. package/src/templates/tamperProtectionTemplates.ts +120 -120
  70. package/src/templates/template.ts +224 -224
  71. package/src/transforms/astScrambler.ts +99 -99
  72. package/src/transforms/calculator.ts +99 -99
  73. package/src/transforms/controlFlowFlattening.ts +1716 -1664
  74. package/src/transforms/deadCode.ts +82 -82
  75. package/src/transforms/dispatcher.ts +450 -450
  76. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +156 -158
  77. package/src/transforms/extraction/objectExtraction.ts +186 -186
  78. package/src/transforms/finalizer.ts +74 -74
  79. package/src/transforms/flatten.ts +421 -420
  80. package/src/transforms/identifier/globalConcealing.ts +315 -295
  81. package/src/transforms/identifier/movedDeclarations.ts +252 -251
  82. package/src/transforms/identifier/renameVariables.ts +328 -321
  83. package/src/transforms/lock/integrity.ts +117 -114
  84. package/src/transforms/lock/lock.ts +418 -425
  85. package/src/transforms/minify.ts +615 -629
  86. package/src/transforms/opaquePredicates.ts +100 -100
  87. package/src/transforms/pack.ts +239 -231
  88. package/src/transforms/plugin.ts +173 -173
  89. package/src/transforms/preparation.ts +349 -347
  90. package/src/transforms/renameLabels.ts +175 -175
  91. package/src/transforms/rgf.ts +322 -322
  92. package/src/transforms/shuffle.ts +82 -82
  93. package/src/transforms/string/encoding.ts +144 -144
  94. package/src/transforms/string/stringCompression.ts +128 -128
  95. package/src/transforms/string/stringConcealing.ts +312 -298
  96. package/src/transforms/string/stringEncoding.ts +80 -80
  97. package/src/transforms/string/stringSplitting.ts +77 -77
  98. package/src/transforms/variableMasking.ts +257 -257
  99. package/src/utils/IntGen.ts +33 -33
  100. package/src/utils/NameGen.ts +116 -116
  101. package/src/utils/PredicateGen.ts +61 -61
  102. package/src/utils/ast-utils.ts +663 -663
  103. package/src/utils/function-utils.ts +50 -50
  104. package/src/utils/gen-utils.ts +48 -48
  105. package/src/utils/node.ts +78 -78
  106. package/src/utils/object-utils.ts +21 -21
  107. package/src/utils/random-utils.ts +93 -93
  108. package/src/utils/static-utils.ts +66 -66
  109. package/src/validateOptions.ts +256 -259
  110. package/tsconfig.json +13 -14
  111. package/dist/probability.js +0 -1
  112. package/dist/transforms/functionOutlining.js +0 -230
  113. package/dist/utils/ControlObject.js +0 -125
@@ -1,322 +1,322 @@
1
- import { NodePath } from "@babel/traverse";
2
- import { PluginArg, PluginObject } from "./plugin";
3
- import { Order } from "../order";
4
- import * as t from "@babel/types";
5
- import Obfuscator from "../obfuscator";
6
- import {
7
- append,
8
- getFunctionName,
9
- isDefiningIdentifier,
10
- isStrictMode,
11
- isVariableIdentifier,
12
- prepend,
13
- } from "../utils/ast-utils";
14
- import {
15
- MULTI_TRANSFORM,
16
- NodeSymbol,
17
- PREDICTABLE,
18
- reservedIdentifiers,
19
- SKIP,
20
- UNSAFE,
21
- } from "../constants";
22
- import { computeFunctionLength } from "../utils/function-utils";
23
- import { numericLiteral } from "../utils/node";
24
- import Template from "../templates/template";
25
- import { createEvalIntegrityTemplate } from "../templates/tamperProtectionTemplates";
26
-
27
- const RGF_ELIGIBLE = Symbol("rgfEligible");
28
-
29
- /**
30
- * RGF (Runtime-Generated-Function) uses the `new Function("code")` syntax to create executable code from strings.
31
- *
32
- * Limitations:
33
- *
34
- * 1. Does not apply to async or generator functions
35
- * 2. Does not apply to functions that reference outside variables
36
- */
37
- export default ({ Plugin }: PluginArg): PluginObject => {
38
- const me = Plugin(Order.RGF, {
39
- changeData: {
40
- functions: 0,
41
- },
42
- });
43
-
44
- const rgfArrayName = me.getPlaceholder() + "_rgf";
45
- const rgfEvalName = me.getPlaceholder() + "_rgf_eval";
46
- const rgfArrayExpression = t.arrayExpression([]);
47
-
48
- let active = true;
49
-
50
- return {
51
- visitor: {
52
- Program: {
53
- enter(path) {
54
- path.scope.crawl();
55
- },
56
- exit(path) {
57
- active = false;
58
- if (rgfArrayExpression.elements.length === 0) return;
59
-
60
- // Insert the RGF array at the top of the program
61
- prepend(
62
- path,
63
- t.variableDeclaration("var", [
64
- t.variableDeclarator(
65
- t.identifier(rgfArrayName),
66
- rgfArrayExpression
67
- ),
68
- ])
69
- );
70
-
71
- var rgfEvalIntegrity = me.getPlaceholder() + "_rgf_eval_integrity";
72
-
73
- prepend(
74
- path,
75
- new Template(`
76
- {EvalIntegrity}
77
- var ${rgfEvalIntegrity} = {EvalIntegrityName}();
78
- `).compile({
79
- EvalIntegrity: createEvalIntegrityTemplate(me, path),
80
- EvalIntegrityName: me.getPlaceholder(),
81
- })
82
- );
83
-
84
- append(
85
- path,
86
- new Template(
87
- `
88
- function ${rgfEvalName}(code) {
89
- if (${rgfEvalIntegrity}) {
90
- return eval(code);
91
- }
92
- }
93
- `
94
- )
95
- .addSymbols(UNSAFE)
96
- .single()
97
- );
98
- },
99
- },
100
- "FunctionDeclaration|FunctionExpression": {
101
- enter(_path) {
102
- if (!active) return;
103
-
104
- // On enter, determine if Function is eligible for RGF transformation
105
-
106
- const path = _path as NodePath<
107
- t.FunctionDeclaration | t.FunctionExpression
108
- >;
109
-
110
- if (me.isSkipped(path)) return;
111
-
112
- // Skip nested functions if the parent function is already deemed eligible
113
- if (path.find((p) => p.node[RGF_ELIGIBLE] || p.node[MULTI_TRANSFORM]))
114
- return;
115
-
116
- // Skip async and generator functions
117
- if (path.node.async || path.node.generator) return;
118
-
119
- const name = getFunctionName(path);
120
- if (name === me.options.lock?.countermeasures) return;
121
- if (me.obfuscator.isInternalVariable(name)) return;
122
-
123
- if (
124
- !me.computeProbabilityMap(
125
- me.options.rgf,
126
- name,
127
- path.getFunctionParent() === null
128
- )
129
- )
130
- return;
131
-
132
- // Skip functions with references to outside variables
133
- // Check the scope to see if this function relies on any variables defined outside the function
134
- var identifierPreventingTransform: string;
135
-
136
- path.traverse({
137
- Identifier(idPath) {
138
- if (!isVariableIdentifier(idPath)) return;
139
- if (idPath.isBindingIdentifier() && isDefiningIdentifier(idPath))
140
- return;
141
-
142
- const { name } = idPath.node;
143
- // RGF array name is allowed, it is not considered an outside reference
144
- if (name === rgfArrayName) return;
145
- if (reservedIdentifiers.has(name)) return;
146
- if (me.options.globalVariables.has(name)) return;
147
-
148
- const binding = idPath.scope.getBinding(name);
149
- if (!binding) {
150
- // Global variables are allowed
151
- return;
152
- }
153
-
154
- var isOutsideVariable =
155
- path.scope.parent.getBinding(name) === binding;
156
- // If the binding is not in the current scope, it is an outside reference
157
- if (isOutsideVariable) {
158
- identifierPreventingTransform = name;
159
- idPath.stop();
160
- }
161
- },
162
- });
163
-
164
- if (identifierPreventingTransform) {
165
- me.log(
166
- "Skipping function " +
167
- name +
168
- " due to reference to outside variable: " +
169
- identifierPreventingTransform
170
- );
171
- return;
172
- }
173
-
174
- me.log("Function " + name + " is eligible for RGF transformation");
175
- path.node[RGF_ELIGIBLE] = true;
176
- },
177
- exit(_path) {
178
- if (!active) return;
179
-
180
- const path = _path as NodePath<
181
- t.FunctionDeclaration | t.FunctionExpression
182
- >;
183
-
184
- if (me.isSkipped(path)) return;
185
-
186
- // Function is not eligible for RGF transformation
187
- if (!path.node[RGF_ELIGIBLE]) return;
188
-
189
- const embeddedName = me.getPlaceholder() + "_embedded";
190
- const replacementName = me.getPlaceholder() + "_replacement";
191
- const argumentsName = me.getPlaceholder() + "_args";
192
-
193
- const lastNode = t.expressionStatement(t.identifier(embeddedName));
194
- (lastNode as NodeSymbol)[SKIP] = true;
195
-
196
- // Transform the function
197
- const evalProgram: t.Program = t.program([
198
- t.functionDeclaration(
199
- t.identifier(embeddedName),
200
- [],
201
- t.blockStatement([
202
- t.variableDeclaration("var", [
203
- t.variableDeclarator(
204
- t.arrayPattern([
205
- t.identifier(rgfArrayName),
206
- t.identifier(argumentsName),
207
- ]),
208
- t.identifier("arguments")
209
- ),
210
- ]),
211
- t.functionDeclaration(
212
- t.identifier(replacementName),
213
- path.node.params as (t.Identifier | t.Pattern)[],
214
- path.node.body
215
- ),
216
- t.returnStatement(
217
- t.callExpression(
218
- t.memberExpression(
219
- t.identifier(replacementName),
220
- t.identifier("apply")
221
- ),
222
- [t.thisExpression(), t.identifier(argumentsName)]
223
- )
224
- ),
225
- ])
226
- ),
227
- lastNode,
228
- ]);
229
-
230
- const strictModeEnforcingBlock = path.find((p) => isStrictMode(p));
231
- if (strictModeEnforcingBlock) {
232
- // Preserve 'use strict' directive
233
- // This is necessary to enure subsequent transforms (Control Flow Flattening) are aware of the strict mode directive
234
- evalProgram.directives.push(
235
- t.directive(t.directiveLiteral("use strict"))
236
- );
237
- }
238
-
239
- const evalFile = t.file(evalProgram);
240
-
241
- var newObfuscator = new Obfuscator(me.options, me.obfuscator);
242
-
243
- var hasRan = new Set(
244
- me.obfuscator.plugins
245
- .filter((plugin, i) => {
246
- return i <= me.obfuscator.index;
247
- })
248
- .map((plugin) => plugin.pluginInstance.order)
249
- );
250
-
251
- // Global Concealing will likely cause issues when Pack is also enabled
252
- const disallowedTransforms = new Set([Order.GlobalConcealing]);
253
-
254
- newObfuscator.plugins = newObfuscator.plugins.filter(
255
- ({ pluginInstance }) => {
256
- return (
257
- (pluginInstance.order == Order.Preparation ||
258
- !hasRan.has(pluginInstance.order)) &&
259
- !disallowedTransforms.has(pluginInstance.order)
260
- );
261
- }
262
- );
263
-
264
- newObfuscator.obfuscateAST(evalFile);
265
-
266
- const generated = Obfuscator.generateCode(evalFile);
267
-
268
- var functionExpression = t.callExpression(t.identifier(rgfEvalName), [
269
- t.stringLiteral(generated),
270
- ]);
271
-
272
- var index = rgfArrayExpression.elements.length;
273
- rgfArrayExpression.elements.push(functionExpression);
274
-
275
- // Params no longer needed, using 'arguments' instead
276
- const originalLength = computeFunctionLength(path);
277
- path.node.params = [];
278
-
279
- // Function is now unsafe
280
- (path.node as NodeSymbol)[UNSAFE] = true;
281
- // Params changed and using 'arguments'
282
- (path.node as NodeSymbol)[PREDICTABLE] = false;
283
- me.skip(path);
284
-
285
- // Update body to point to new function
286
- path
287
- .get("body")
288
- .replaceWith(
289
- t.blockStatement([
290
- t.returnStatement(
291
- t.callExpression(
292
- t.memberExpression(
293
- t.memberExpression(
294
- t.identifier(rgfArrayName),
295
- numericLiteral(index),
296
- true
297
- ),
298
- t.stringLiteral("apply"),
299
- true
300
- ),
301
- [
302
- t.thisExpression(),
303
- t.arrayExpression([
304
- t.identifier(rgfArrayName),
305
- t.identifier("arguments"),
306
- ]),
307
- ]
308
- )
309
- ),
310
- ])
311
- );
312
-
313
- path.skip();
314
-
315
- me.setFunctionLength(path, originalLength);
316
-
317
- me.changeData.functions++;
318
- },
319
- },
320
- },
321
- };
322
- };
1
+ import { NodePath } from "@babel/traverse";
2
+ import { PluginArg, PluginObject } from "./plugin";
3
+ import { Order } from "../order";
4
+ import * as t from "@babel/types";
5
+ import Obfuscator from "../obfuscator";
6
+ import {
7
+ append,
8
+ getFunctionName,
9
+ isDefiningIdentifier,
10
+ isStrictMode,
11
+ isVariableIdentifier,
12
+ prepend,
13
+ } from "../utils/ast-utils";
14
+ import {
15
+ MULTI_TRANSFORM,
16
+ NodeSymbol,
17
+ PREDICTABLE,
18
+ reservedIdentifiers,
19
+ SKIP,
20
+ UNSAFE,
21
+ } from "../constants";
22
+ import { computeFunctionLength } from "../utils/function-utils";
23
+ import { numericLiteral } from "../utils/node";
24
+ import Template from "../templates/template";
25
+ import { createEvalIntegrityTemplate } from "../templates/tamperProtectionTemplates";
26
+
27
+ const RGF_ELIGIBLE = Symbol("rgfEligible");
28
+
29
+ /**
30
+ * RGF (Runtime-Generated-Function) uses the `new Function("code")` syntax to create executable code from strings.
31
+ *
32
+ * Limitations:
33
+ *
34
+ * 1. Does not apply to async or generator functions
35
+ * 2. Does not apply to functions that reference outside variables
36
+ */
37
+ export default ({ Plugin }: PluginArg): PluginObject => {
38
+ const me = Plugin(Order.RGF, {
39
+ changeData: {
40
+ functions: 0,
41
+ },
42
+ });
43
+
44
+ const rgfArrayName = me.getPlaceholder() + "_rgf";
45
+ const rgfEvalName = me.getPlaceholder() + "_rgf_eval";
46
+ const rgfArrayExpression = t.arrayExpression([]);
47
+
48
+ let active = true;
49
+
50
+ return {
51
+ visitor: {
52
+ Program: {
53
+ enter(path) {
54
+ path.scope.crawl();
55
+ },
56
+ exit(path) {
57
+ active = false;
58
+ if (rgfArrayExpression.elements.length === 0) return;
59
+
60
+ // Insert the RGF array at the top of the program
61
+ prepend(
62
+ path,
63
+ t.variableDeclaration("var", [
64
+ t.variableDeclarator(
65
+ t.identifier(rgfArrayName),
66
+ rgfArrayExpression
67
+ ),
68
+ ])
69
+ );
70
+
71
+ var rgfEvalIntegrity = me.getPlaceholder() + "_rgf_eval_integrity";
72
+
73
+ prepend(
74
+ path,
75
+ new Template(`
76
+ {EvalIntegrity}
77
+ var ${rgfEvalIntegrity} = {EvalIntegrityName}();
78
+ `).compile({
79
+ EvalIntegrity: createEvalIntegrityTemplate(me, path),
80
+ EvalIntegrityName: me.getPlaceholder(),
81
+ })
82
+ );
83
+
84
+ append(
85
+ path,
86
+ new Template(
87
+ `
88
+ function ${rgfEvalName}(code) {
89
+ if (${rgfEvalIntegrity}) {
90
+ return eval(code);
91
+ }
92
+ }
93
+ `
94
+ )
95
+ .addSymbols(UNSAFE)
96
+ .single()
97
+ );
98
+ },
99
+ },
100
+ "FunctionDeclaration|FunctionExpression": {
101
+ enter(_path) {
102
+ if (!active) return;
103
+
104
+ // On enter, determine if Function is eligible for RGF transformation
105
+
106
+ const path = _path as NodePath<
107
+ t.FunctionDeclaration | t.FunctionExpression
108
+ >;
109
+
110
+ if (me.isSkipped(path)) return;
111
+
112
+ // Skip nested functions if the parent function is already deemed eligible
113
+ if (path.find((p) => p.node[RGF_ELIGIBLE] || p.node[MULTI_TRANSFORM]))
114
+ return;
115
+
116
+ // Skip async and generator functions
117
+ if (path.node.async || path.node.generator) return;
118
+
119
+ const name = getFunctionName(path);
120
+ if (name === me.options.lock?.countermeasures) return;
121
+ if (me.obfuscator.isInternalVariable(name)) return;
122
+
123
+ if (
124
+ !me.computeProbabilityMap(
125
+ me.options.rgf,
126
+ name,
127
+ path.getFunctionParent() === null
128
+ )
129
+ )
130
+ return;
131
+
132
+ // Skip functions with references to outside variables
133
+ // Check the scope to see if this function relies on any variables defined outside the function
134
+ var identifierPreventingTransform: string;
135
+
136
+ path.traverse({
137
+ Identifier(idPath) {
138
+ if (!isVariableIdentifier(idPath)) return;
139
+ if (idPath.isBindingIdentifier() && isDefiningIdentifier(idPath))
140
+ return;
141
+
142
+ const { name } = idPath.node;
143
+ // RGF array name is allowed, it is not considered an outside reference
144
+ if (name === rgfArrayName) return;
145
+ if (reservedIdentifiers.has(name)) return;
146
+ if (me.options.globalVariables.has(name)) return;
147
+
148
+ const binding = idPath.scope.getBinding(name);
149
+ if (!binding) {
150
+ // Global variables are allowed
151
+ return;
152
+ }
153
+
154
+ var isOutsideVariable =
155
+ path.scope.parent.getBinding(name) === binding;
156
+ // If the binding is not in the current scope, it is an outside reference
157
+ if (isOutsideVariable) {
158
+ identifierPreventingTransform = name;
159
+ idPath.stop();
160
+ }
161
+ },
162
+ });
163
+
164
+ if (identifierPreventingTransform) {
165
+ me.log(
166
+ "Skipping function " +
167
+ name +
168
+ " due to reference to outside variable: " +
169
+ identifierPreventingTransform
170
+ );
171
+ return;
172
+ }
173
+
174
+ me.log("Function " + name + " is eligible for RGF transformation");
175
+ path.node[RGF_ELIGIBLE] = true;
176
+ },
177
+ exit(_path) {
178
+ if (!active) return;
179
+
180
+ const path = _path as NodePath<
181
+ t.FunctionDeclaration | t.FunctionExpression
182
+ >;
183
+
184
+ if (me.isSkipped(path)) return;
185
+
186
+ // Function is not eligible for RGF transformation
187
+ if (!path.node[RGF_ELIGIBLE]) return;
188
+
189
+ const embeddedName = me.getPlaceholder() + "_embedded";
190
+ const replacementName = me.getPlaceholder() + "_replacement";
191
+ const argumentsName = me.getPlaceholder() + "_args";
192
+
193
+ const lastNode = t.expressionStatement(t.identifier(embeddedName));
194
+ (lastNode as NodeSymbol)[SKIP] = true;
195
+
196
+ // Transform the function
197
+ const evalProgram: t.Program = t.program([
198
+ t.functionDeclaration(
199
+ t.identifier(embeddedName),
200
+ [],
201
+ t.blockStatement([
202
+ t.variableDeclaration("var", [
203
+ t.variableDeclarator(
204
+ t.arrayPattern([
205
+ t.identifier(rgfArrayName),
206
+ t.identifier(argumentsName),
207
+ ]),
208
+ t.identifier("arguments")
209
+ ),
210
+ ]),
211
+ t.functionDeclaration(
212
+ t.identifier(replacementName),
213
+ path.node.params as (t.Identifier | t.Pattern)[],
214
+ path.node.body
215
+ ),
216
+ t.returnStatement(
217
+ t.callExpression(
218
+ t.memberExpression(
219
+ t.identifier(replacementName),
220
+ t.identifier("apply")
221
+ ),
222
+ [t.thisExpression(), t.identifier(argumentsName)]
223
+ )
224
+ ),
225
+ ])
226
+ ),
227
+ lastNode,
228
+ ]);
229
+
230
+ const strictModeEnforcingBlock = path.find((p) => isStrictMode(p));
231
+ if (strictModeEnforcingBlock) {
232
+ // Preserve 'use strict' directive
233
+ // This is necessary to enure subsequent transforms (Control Flow Flattening) are aware of the strict mode directive
234
+ evalProgram.directives.push(
235
+ t.directive(t.directiveLiteral("use strict"))
236
+ );
237
+ }
238
+
239
+ const evalFile = t.file(evalProgram);
240
+
241
+ var newObfuscator = new Obfuscator(me.options, me.obfuscator);
242
+
243
+ var hasRan = new Set(
244
+ me.obfuscator.plugins
245
+ .filter((plugin, i) => {
246
+ return i <= me.obfuscator.index;
247
+ })
248
+ .map((plugin) => plugin.pluginInstance.order)
249
+ );
250
+
251
+ // Global Concealing will likely cause issues when Pack is also enabled
252
+ const disallowedTransforms = new Set([Order.GlobalConcealing]);
253
+
254
+ newObfuscator.plugins = newObfuscator.plugins.filter(
255
+ ({ pluginInstance }) => {
256
+ return (
257
+ (pluginInstance.order == Order.Preparation ||
258
+ !hasRan.has(pluginInstance.order)) &&
259
+ !disallowedTransforms.has(pluginInstance.order)
260
+ );
261
+ }
262
+ );
263
+
264
+ newObfuscator.obfuscateAST(evalFile);
265
+
266
+ const generated = Obfuscator.generateCode(evalFile);
267
+
268
+ var functionExpression = t.callExpression(t.identifier(rgfEvalName), [
269
+ t.stringLiteral(generated),
270
+ ]);
271
+
272
+ var index = rgfArrayExpression.elements.length;
273
+ rgfArrayExpression.elements.push(functionExpression);
274
+
275
+ // Params no longer needed, using 'arguments' instead
276
+ const originalLength = computeFunctionLength(path);
277
+ path.node.params = [];
278
+
279
+ // Function is now unsafe
280
+ (path.node as NodeSymbol)[UNSAFE] = true;
281
+ // Params changed and using 'arguments'
282
+ (path.node as NodeSymbol)[PREDICTABLE] = false;
283
+ me.skip(path);
284
+
285
+ // Update body to point to new function
286
+ path
287
+ .get("body")
288
+ .replaceWith(
289
+ t.blockStatement([
290
+ t.returnStatement(
291
+ t.callExpression(
292
+ t.memberExpression(
293
+ t.memberExpression(
294
+ t.identifier(rgfArrayName),
295
+ numericLiteral(index),
296
+ true
297
+ ),
298
+ t.stringLiteral("apply"),
299
+ true
300
+ ),
301
+ [
302
+ t.thisExpression(),
303
+ t.arrayExpression([
304
+ t.identifier(rgfArrayName),
305
+ t.identifier("arguments"),
306
+ ]),
307
+ ]
308
+ )
309
+ ),
310
+ ])
311
+ );
312
+
313
+ path.skip();
314
+
315
+ me.setFunctionLength(path, originalLength);
316
+
317
+ me.changeData.functions++;
318
+ },
319
+ },
320
+ },
321
+ };
322
+ };