js-confuser 1.5.9 → 1.7.0

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 (143) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +346 -165
  4. package/dist/constants.js +6 -2
  5. package/dist/index.js +9 -21
  6. package/dist/obfuscator.js +19 -31
  7. package/dist/options.js +5 -5
  8. package/dist/order.js +1 -3
  9. package/dist/presets.js +6 -7
  10. package/dist/probability.js +2 -4
  11. package/dist/templates/bufferToString.js +13 -0
  12. package/dist/templates/crash.js +3 -3
  13. package/dist/templates/es5.js +18 -0
  14. package/dist/templates/functionLength.js +16 -0
  15. package/dist/transforms/calculator.js +77 -21
  16. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  17. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
  18. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  19. package/dist/transforms/deadCode.js +33 -25
  20. package/dist/transforms/dispatcher.js +8 -4
  21. package/dist/transforms/es5/antiDestructuring.js +2 -0
  22. package/dist/transforms/es5/es5.js +31 -34
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
  24. package/dist/transforms/finalizer.js +82 -0
  25. package/dist/transforms/flatten.js +229 -148
  26. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  27. package/dist/transforms/identifier/globalConcealing.js +10 -83
  28. package/dist/transforms/identifier/movedDeclarations.js +35 -88
  29. package/dist/transforms/identifier/renameVariables.js +124 -59
  30. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  31. package/dist/transforms/lock/lock.js +0 -37
  32. package/dist/transforms/minify.js +60 -57
  33. package/dist/transforms/opaquePredicates.js +1 -1
  34. package/dist/transforms/preparation/preparation.js +2 -2
  35. package/dist/transforms/preparation.js +231 -0
  36. package/dist/transforms/renameLabels.js +1 -1
  37. package/dist/transforms/rgf.js +139 -247
  38. package/dist/transforms/stack.js +128 -26
  39. package/dist/transforms/string/encoding.js +150 -179
  40. package/dist/transforms/string/stringCompression.js +14 -15
  41. package/dist/transforms/string/stringConcealing.js +25 -8
  42. package/dist/transforms/string/stringEncoding.js +13 -24
  43. package/dist/transforms/transform.js +12 -19
  44. package/dist/traverse.js +24 -10
  45. package/dist/util/gen.js +17 -1
  46. package/dist/util/identifiers.js +37 -3
  47. package/dist/util/insert.js +35 -4
  48. package/dist/util/random.js +15 -0
  49. package/docs/ControlFlowFlattening.md +595 -0
  50. package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
  51. package/{Integrity.md → docs/Integrity.md} +2 -2
  52. package/docs/RGF.md +419 -0
  53. package/package.json +5 -5
  54. package/src/constants.ts +3 -0
  55. package/src/index.ts +2 -2
  56. package/src/obfuscator.ts +19 -31
  57. package/src/options.ts +14 -103
  58. package/src/order.ts +1 -5
  59. package/src/presets.ts +6 -7
  60. package/src/probability.ts +2 -3
  61. package/src/templates/bufferToString.ts +68 -0
  62. package/src/templates/crash.ts +15 -19
  63. package/src/templates/es5.ts +131 -0
  64. package/src/templates/functionLength.ts +14 -0
  65. package/src/transforms/calculator.ts +122 -59
  66. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  67. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
  68. package/src/transforms/deadCode.ts +383 -26
  69. package/src/transforms/dispatcher.ts +9 -4
  70. package/src/transforms/es5/antiDestructuring.ts +2 -0
  71. package/src/transforms/es5/es5.ts +32 -77
  72. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
  73. package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
  74. package/src/transforms/flatten.ts +357 -300
  75. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  76. package/src/transforms/identifier/globalConcealing.ts +14 -103
  77. package/src/transforms/identifier/movedDeclarations.ts +49 -102
  78. package/src/transforms/identifier/renameVariables.ts +149 -78
  79. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  80. package/src/transforms/lock/lock.ts +1 -42
  81. package/src/transforms/minify.ts +91 -75
  82. package/src/transforms/opaquePredicates.ts +2 -2
  83. package/src/transforms/preparation.ts +238 -0
  84. package/src/transforms/renameLabels.ts +2 -2
  85. package/src/transforms/rgf.ts +213 -405
  86. package/src/transforms/stack.ts +156 -36
  87. package/src/transforms/string/encoding.ts +115 -212
  88. package/src/transforms/string/stringCompression.ts +27 -18
  89. package/src/transforms/string/stringConcealing.ts +39 -9
  90. package/src/transforms/string/stringEncoding.ts +18 -18
  91. package/src/transforms/transform.ts +21 -23
  92. package/src/traverse.ts +23 -4
  93. package/src/types.ts +2 -1
  94. package/src/util/gen.ts +28 -3
  95. package/src/util/identifiers.ts +43 -2
  96. package/src/util/insert.ts +38 -3
  97. package/src/util/random.ts +13 -0
  98. package/test/code/Cash.test.ts +1 -1
  99. package/test/code/Dynamic.test.ts +12 -10
  100. package/test/code/ES6.src.js +146 -0
  101. package/test/code/ES6.test.ts +28 -2
  102. package/test/index.test.ts +2 -1
  103. package/test/probability.test.ts +44 -0
  104. package/test/templates/template.test.ts +1 -1
  105. package/test/transforms/antiTooling.test.ts +22 -0
  106. package/test/transforms/calculator.test.ts +40 -0
  107. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
  108. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  109. package/test/transforms/deadCode.test.ts +66 -15
  110. package/test/transforms/dispatcher.test.ts +20 -1
  111. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  112. package/test/transforms/flatten.test.ts +399 -86
  113. package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
  114. package/test/transforms/identifier/renameVariables.test.ts +119 -0
  115. package/test/transforms/lock/antiDebug.test.ts +2 -2
  116. package/test/transforms/lock/lock.test.ts +1 -48
  117. package/test/transforms/minify.test.ts +104 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +261 -381
  120. package/test/transforms/stack.test.ts +143 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +82 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/identifiers.test.ts +113 -1
  127. package/test/util/insert.test.ts +57 -3
  128. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  129. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  130. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  131. package/src/transforms/eval.ts +0 -89
  132. package/src/transforms/hideInitializingCode.ts +0 -432
  133. package/src/transforms/identifier/nameRecycling.ts +0 -280
  134. package/src/transforms/label.ts +0 -64
  135. package/src/transforms/preparation/nameConflicts.ts +0 -102
  136. package/src/transforms/preparation/preparation.ts +0 -176
  137. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  138. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  139. package/test/transforms/eval.test.ts +0 -131
  140. package/test/transforms/hideInitializingCode.test.ts +0 -336
  141. package/test/transforms/identifier/nameRecycling.test.ts +0 -205
  142. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  143. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -1,432 +0,0 @@
1
- import { reservedIdentifiers } from "../constants";
2
- import { ObfuscateOrder } from "../order";
3
- import { walk } from "../traverse";
4
- import {
5
- AssignmentExpression,
6
- BinaryExpression,
7
- BreakStatement,
8
- CallExpression,
9
- ConditionalExpression,
10
- ExpressionStatement,
11
- FunctionDeclaration,
12
- FunctionExpression,
13
- Identifier,
14
- Literal,
15
- MemberExpression,
16
- ReturnStatement,
17
- SequenceExpression,
18
- SwitchCase,
19
- SwitchStatement,
20
- ThisExpression,
21
- UnaryExpression,
22
- VariableDeclaration,
23
- VariableDeclarator,
24
- } from "../util/gen";
25
- import { getIdentifierInfo, validateChain } from "../util/identifiers";
26
- import { getVarContext, isForInitialize, isFunction } from "../util/insert";
27
- import { choice, getRandomInteger, shuffle } from "../util/random";
28
- import Transform from "./transform";
29
-
30
- export default class HideInitializingCode extends Transform {
31
- constructor(o) {
32
- super(o, ObfuscateOrder.HideInitializingCode);
33
- }
34
-
35
- match(object, parents) {
36
- return object.type == "Program";
37
- }
38
-
39
- transform(object, parents) {
40
- return () => {
41
- var body = object.body;
42
- var hasExport = false;
43
-
44
- var stmts = [];
45
- var functions = [];
46
- var exportTypes = new Set([
47
- "ExportNamedDeclaration",
48
- "ExportSpecifier",
49
- "ExportDefaultDeclaration",
50
- "ExportAllDeclaration",
51
- ]);
52
-
53
- var sampledNames = new Set<string>();
54
-
55
- body.forEach((stmt) => {
56
- if (stmt.type == "FunctionDeclaration") {
57
- functions.push(stmt);
58
- if (stmt.id) {
59
- sampledNames.add(stmt.id.name);
60
- }
61
- } else if (exportTypes.has(stmt.type)) {
62
- hasExport = true;
63
- } else {
64
- stmts.push(stmt);
65
- }
66
- });
67
-
68
- if (hasExport) {
69
- return;
70
- }
71
-
72
- var definedNames = new Set<string>();
73
-
74
- const findNames = (o, p) => {
75
- validateChain(o, p);
76
- var context = getVarContext(o, p);
77
- walk(o, p, (oo, pp) => {
78
- if (
79
- oo.type == "Identifier" &&
80
- !reservedIdentifiers.has(oo.name) &&
81
- !this.options.globalVariables.has(oo.name)
82
- ) {
83
- var info = getIdentifierInfo(oo, pp);
84
- if (
85
- info.spec.isReferenced &&
86
- info.spec.isDefined &&
87
- getVarContext(oo, pp) === context
88
- ) {
89
- definedNames.add(oo.name);
90
- }
91
- }
92
- });
93
- };
94
-
95
- walk(object, [], (o, p) => {
96
- if (o.type == "VariableDeclaration" || o.type == "ClassDeclaration") {
97
- if (p.find((x) => isFunction(x))) {
98
- return;
99
- }
100
- if (o.type == "VariableDeclaration") {
101
- return () => {
102
- var exprs = [];
103
- var fi = isForInitialize(o, p);
104
- o.declarations.forEach((declarator) => {
105
- findNames(declarator.id, [declarator, o.declarations, o, ...p]);
106
- if (fi === "left-hand") {
107
- exprs.push({ ...declarator.id });
108
- } else {
109
- exprs.push(
110
- AssignmentExpression(
111
- "=",
112
- declarator.id,
113
- declarator.init || Identifier("undefined")
114
- )
115
- );
116
- }
117
- });
118
-
119
- if (fi) {
120
- this.replace(
121
- o,
122
- exprs.length > 1 ? SequenceExpression(exprs) : exprs[0]
123
- );
124
- } else {
125
- this.replace(o, ExpressionStatement(SequenceExpression(exprs)));
126
- }
127
- };
128
- } else if (o.type == "ClassDeclaration") {
129
- if (o.id.name) {
130
- definedNames.add(o.id.name);
131
-
132
- this.replace(
133
- o,
134
- ExpressionStatement(
135
- AssignmentExpression("=", Identifier(o.id.name), {
136
- ...o,
137
- type: "ClassExpression",
138
- })
139
- )
140
- );
141
- }
142
- }
143
- }
144
- });
145
-
146
- var addNodes = [];
147
- if (definedNames.size) {
148
- addNodes.push(
149
- VariableDeclaration(
150
- Array.from(definedNames).map((name) => {
151
- return VariableDeclarator(name);
152
- })
153
- )
154
- );
155
- }
156
-
157
- var deadValues: { [name: string]: number } = Object.create(null);
158
- Array(getRandomInteger(1, 20))
159
- .fill(0)
160
- .forEach(() => {
161
- var name = this.getPlaceholder();
162
- var value = getRandomInteger(-250, 250);
163
- addNodes.push(
164
- VariableDeclaration(VariableDeclarator(name, Literal(value)))
165
- );
166
-
167
- deadValues[name] = value;
168
- sampledNames.add(name);
169
- });
170
-
171
- var map = new Map<string, { [input: number]: number }>();
172
- var fnsToMake = getRandomInteger(1, 5);
173
-
174
- var numberLiteralsMade = 1;
175
- function numberLiteral(num: number, depth = 1) {
176
- if (
177
- depth > 6 ||
178
- Math.random() > 0.8 / depth ||
179
- Math.random() > 80 / numberLiteralsMade
180
- ) {
181
- return Literal(num);
182
- }
183
-
184
- numberLiteralsMade++;
185
-
186
- function ternaryCall(
187
- name: string,
188
- param: number = getRandomInteger(-250, 250)
189
- ) {
190
- return ConditionalExpression(
191
- BinaryExpression(
192
- "==",
193
- UnaryExpression("typeof", Identifier(name)),
194
- Literal("function")
195
- ),
196
- CallExpression(Identifier(name), [numberLiteral(param, depth + 1)]),
197
- Identifier(name)
198
- );
199
- }
200
-
201
- if (Math.random() > 0.5) {
202
- var fnName = choice(Array.from(map.keys()));
203
- if (fnName) {
204
- var inputOutputs = map.get(fnName);
205
- var randomInput = choice(Object.keys(inputOutputs));
206
- var outputValue = inputOutputs[randomInput];
207
- var parsed = parseFloat(randomInput);
208
-
209
- return BinaryExpression(
210
- "-",
211
-
212
- ternaryCall(fnName, parsed),
213
- numberLiteral(outputValue - num, depth + 1)
214
- );
215
- }
216
- }
217
-
218
- var deadValueName = choice(Object.keys(deadValues));
219
- var actualValue = deadValues[deadValueName];
220
-
221
- if (Math.random() > 0.5) {
222
- return BinaryExpression(
223
- "+",
224
- numberLiteral(num - actualValue, depth + 1),
225
- ternaryCall(deadValueName)
226
- );
227
- }
228
-
229
- return BinaryExpression(
230
- "-",
231
- ternaryCall(deadValueName),
232
- numberLiteral(actualValue - num, depth + 1)
233
- );
234
- }
235
-
236
- for (var i = 0; i < fnsToMake; i++) {
237
- var name = this.getPlaceholder();
238
- var testShift = getRandomInteger(-250, 250);
239
- var returnShift = getRandomInteger(-250, 250);
240
-
241
- var inputs = getRandomInteger(2, 5);
242
- var used = new Set<number>();
243
- var uniqueNumbersNeeded = inputs * 2;
244
- for (var j = 0; j < uniqueNumbersNeeded; j++) {
245
- var num;
246
- var k = 0;
247
- do {
248
- num = getRandomInteger(-250, 250 + k * 100);
249
- k++;
250
- } while (used.has(num));
251
-
252
- used.add(num);
253
- }
254
-
255
- var inputOutput = Object.create(null);
256
- var array: number[] = Array.from(used);
257
- for (var j = 0; j < array.length; j += 2) {
258
- inputOutput[array[j]] = array[j + 1];
259
- }
260
-
261
- var cases = Object.keys(inputOutput).map((input) => {
262
- var parsed = parseFloat(input);
263
-
264
- return SwitchCase(numberLiteral(parsed + testShift), [
265
- ExpressionStatement(
266
- AssignmentExpression(
267
- "=",
268
- Identifier("input"),
269
- numberLiteral(inputOutput[input] - returnShift)
270
- )
271
- ),
272
- BreakStatement(),
273
- ]);
274
- });
275
-
276
- var functionExpression = FunctionExpression(
277
- [Identifier("testShift"), Identifier("returnShift")],
278
- [
279
- ReturnStatement(
280
- FunctionExpression(
281
- [Identifier("input")],
282
- [
283
- SwitchStatement(
284
- BinaryExpression(
285
- "+",
286
- Identifier("input"),
287
- Identifier("testShift")
288
- ),
289
- cases
290
- ),
291
-
292
- ReturnStatement(
293
- BinaryExpression(
294
- "+",
295
- Identifier("input"),
296
- Identifier("returnShift")
297
- )
298
- ),
299
- ]
300
- )
301
- ),
302
- ]
303
- );
304
-
305
- var variableDeclaration = VariableDeclaration(
306
- VariableDeclarator(
307
- name,
308
- CallExpression(functionExpression, [
309
- numberLiteral(testShift),
310
- numberLiteral(returnShift),
311
- ])
312
- )
313
- );
314
- addNodes.push(variableDeclaration);
315
-
316
- map.set(name, inputOutput);
317
- sampledNames.add(name);
318
- }
319
-
320
- var deadNameArray = Object.keys(deadValues);
321
- var sampledArray = Array.from(sampledNames);
322
-
323
- var check = getRandomInteger(-250, 250);
324
-
325
- var initName = "init" + this.getPlaceholder();
326
-
327
- // Entangle number literals
328
- var made = 1; // Limit frequency
329
- walk(stmts, [], (o, p) => {
330
- if (
331
- o.type == "Literal" &&
332
- typeof o.value === "number" &&
333
- Math.floor(o.value) === o.value &&
334
- Math.abs(o.value) < 100_000 &&
335
- Math.random() < 4 / made
336
- ) {
337
- made++;
338
- return () => {
339
- this.replaceIdentifierOrLiteral(o, numberLiteral(o.value), p);
340
- };
341
- }
342
- });
343
-
344
- // Create the new function
345
- addNodes.push(FunctionDeclaration(initName, [], [...stmts]));
346
-
347
- function truePredicate() {
348
- return BinaryExpression(
349
- ">",
350
- Literal(600 + getRandomInteger(200, 800)),
351
- Literal(400 - getRandomInteger(0, 600))
352
- );
353
- }
354
- function falsePredicate() {
355
- return BinaryExpression(
356
- ">",
357
- Literal(400 - getRandomInteger(0, 600)),
358
- Literal(600 + getRandomInteger(200, 800))
359
- );
360
- }
361
-
362
- function safeCallExpression(name, param: number) {
363
- return ConditionalExpression(
364
- BinaryExpression(
365
- "==",
366
- UnaryExpression("typeof", Identifier(name)),
367
- Literal("function")
368
- ),
369
- CallExpression(
370
- MemberExpression(Identifier(name), Identifier("call"), false),
371
- [ThisExpression(), numberLiteral(param)]
372
- ),
373
- Identifier(name)
374
- );
375
- }
376
-
377
- function ternaryHell(expr, depth = 1) {
378
- if (!depth || depth > 5 || Math.random() > 0.99 / (depth / 2)) {
379
- return expr;
380
- }
381
-
382
- var deadCode = safeCallExpression(
383
- choice(sampledArray),
384
- getRandomInteger(-250, 250)
385
- );
386
-
387
- if (Math.random() > 0.5) {
388
- return ConditionalExpression(
389
- truePredicate(),
390
- ternaryHell(expr, depth + 1),
391
- ternaryHell(deadCode, depth + 1)
392
- );
393
- }
394
-
395
- return ConditionalExpression(
396
- falsePredicate(),
397
- ternaryHell(deadCode, depth + 1),
398
- ternaryHell(expr, depth + 1)
399
- );
400
- }
401
-
402
- // Array of random ternary expressions
403
- var concealedCall = [];
404
-
405
- // Add 'dead calls', these expression don't call anything
406
- Array(getRandomInteger(2, 8))
407
- .fill(0)
408
- .forEach(() => {
409
- concealedCall.push(
410
- ExpressionStatement(
411
- ternaryHell(
412
- safeCallExpression(
413
- choice(deadNameArray),
414
- getRandomInteger(-250, 250)
415
- )
416
- )
417
- )
418
- );
419
- });
420
-
421
- // The real call to the 'init' function
422
- concealedCall.push(
423
- ExpressionStatement(ternaryHell(safeCallExpression(initName, check)))
424
- );
425
-
426
- shuffle(concealedCall);
427
- shuffle(functions);
428
-
429
- object.body = [...addNodes, ...functions, ...concealedCall];
430
- };
431
- }
432
- }
@@ -1,280 +0,0 @@
1
- import { ok } from "assert";
2
- import { ObfuscateOrder } from "../../order";
3
- import { ComputeProbabilityMap } from "../../probability";
4
- import { getBlock, isBlock, walk } from "../../traverse";
5
- import {
6
- AssignmentExpression,
7
- ExpressionStatement,
8
- Identifier,
9
- Location,
10
- VariableDeclarator,
11
- } from "../../util/gen";
12
- import {
13
- containsLexicallyBoundVariables,
14
- getFunctionParameters,
15
- getIdentifierInfo,
16
- } from "../../util/identifiers";
17
- import {
18
- getDefiningContext,
19
- getReferencingContexts,
20
- getVarContext,
21
- isForInitialize,
22
- isFunction,
23
- isVarContext,
24
- } from "../../util/insert";
25
- import Transform from "../transform";
26
-
27
- /**
28
- * Statement-based variable recycling.
29
- *
30
- * ```js
31
- * // Input
32
- * function percentage(decimal) {
33
- * var multiplied = x * 100;
34
- * var floored = Math.floor(multiplied);
35
- * var output = floored + "%"
36
- * return output;
37
- * }
38
- *
39
- * // Output
40
- * function percentage(decimal) {
41
- * var multiplied = x * 100;
42
- * var floored = Math.floor(multiplied);
43
- * multiplied = floored + "%";
44
- * return multiplied;
45
- * }
46
- * ```
47
- */
48
- export default class NameRecycling extends Transform {
49
- constructor(o) {
50
- super(o, ObfuscateOrder.NameRecycling);
51
- }
52
-
53
- match(object, parents) {
54
- return isBlock(object);
55
- }
56
-
57
- transform(object, parents) {
58
- return () => {
59
- if (containsLexicallyBoundVariables(object, parents)) {
60
- return;
61
- }
62
-
63
- var context = getVarContext(object, parents);
64
-
65
- var stmts = [...object.body];
66
- ok(Array.isArray(stmts));
67
-
68
- var definedMap = new Map<number, Set<string>>();
69
- var referencedMap = new Map<number, Set<string>>();
70
- var nodeMap = new Map<number, Map<string, Location[]>>();
71
-
72
- var lastReferenceMap = new Map<string, number>();
73
-
74
- var defined = new Set<string>();
75
- var illegal = new Set<string>();
76
-
77
- var fn = isFunction(parents[0]) ? parents[0] : null;
78
- if (fn) {
79
- definedMap.set(
80
- -1,
81
- new Set(
82
- getFunctionParameters(fn, parents.slice(1)).map((x) => x[0].name)
83
- )
84
- );
85
- }
86
-
87
- stmts.forEach((stmt, i) => {
88
- var definedHere = new Set<string>();
89
- var referencedHere = new Set<string>();
90
- var nodesHere = new Map<string, Location[]>();
91
-
92
- walk(stmt, [object.body, object, ...parents], (o, p) => {
93
- if (o.type == "Identifier") {
94
- return () => {
95
- var info = getIdentifierInfo(o, p);
96
- if (!info.spec.isReferenced) {
97
- return;
98
- }
99
-
100
- var comparingContext = info.spec.isDefined
101
- ? getDefiningContext(o, p)
102
- : getReferencingContexts(o, p).find((x) => isVarContext(x));
103
-
104
- if (comparingContext !== context) {
105
- illegal.add(o.name);
106
- this.log(o.name, "is different context");
107
- } else {
108
- if (!nodesHere.has(o.name)) {
109
- nodesHere.set(o.name, [[o, p]]);
110
- } else {
111
- nodesHere.get(o.name).push([o, p]);
112
- }
113
-
114
- if (info.spec.isDefined) {
115
- // Function Declarations can be used before they're defined, if so, don't change this
116
- if (
117
- info.isFunctionDeclaration &&
118
- lastReferenceMap.has(o.name)
119
- ) {
120
- illegal.add(o.name);
121
- }
122
- if (
123
- defined.has(o.name) ||
124
- getBlock(o, p) !== object ||
125
- info.isImportSpecifier
126
- ) {
127
- illegal.add(o.name);
128
- }
129
- defined.add(o.name);
130
- definedHere.add(o.name);
131
- } else {
132
- referencedHere.add(o.name);
133
- }
134
- }
135
-
136
- lastReferenceMap.set(o.name, i);
137
- };
138
- }
139
- });
140
-
141
- // console.log(i, definedHere);
142
-
143
- definedMap.set(i, definedHere);
144
- referencedMap.set(i, referencedHere);
145
- nodeMap.set(i, nodesHere);
146
- });
147
-
148
- this.log(illegal);
149
-
150
- illegal.forEach((name) => {
151
- nodeMap.forEach((value) => {
152
- value.delete(name);
153
- });
154
- });
155
-
156
- var available = new Set<string>();
157
- var newNames = Object.create(null);
158
-
159
- stmts.forEach((stmt, i) => {
160
- var nodes = nodeMap.get(i);
161
-
162
- nodes.forEach((locations, name) => {
163
- var newName = newNames[name];
164
-
165
- if (!newName) {
166
- var canChange = false;
167
-
168
- if (
169
- object.type == "Program" &&
170
- !ComputeProbabilityMap(this.options.renameGlobals, (x) => x, name)
171
- ) {
172
- return;
173
- }
174
-
175
- if (defined.has(name) && definedMap.get(i).has(name)) {
176
- canChange = true;
177
- }
178
-
179
- if (!canChange) {
180
- return;
181
- }
182
-
183
- if (available.size) {
184
- newName = available.keys().next().value;
185
- available.delete(newName);
186
-
187
- ok(name !== newName);
188
- newNames[name] = newName;
189
-
190
- defined.delete(name);
191
-
192
- this.log(name, "->", newName);
193
- }
194
- }
195
- });
196
-
197
- nodes.forEach((locations, name) => {
198
- var newName = newNames[name];
199
-
200
- if (newName) {
201
- locations.forEach(([object, parents]) => {
202
- object.name = newName;
203
-
204
- var declaratorIndex = parents.findIndex(
205
- (p) => p.type == "VariableDeclarator"
206
- );
207
- if (
208
- declaratorIndex !== -1 &&
209
- parents[declaratorIndex].id ===
210
- (parents[declaratorIndex - 1] || object)
211
- ) {
212
- var value =
213
- parents[declaratorIndex].init || Identifier("undefined");
214
-
215
- var expr = AssignmentExpression(
216
- "=",
217
- parents[declaratorIndex].id,
218
- value
219
- );
220
-
221
- if (parents[declaratorIndex + 1].length === 1) {
222
- if (
223
- isForInitialize(
224
- parents[declaratorIndex + 2],
225
- parents.slice(3)
226
- )
227
- ) {
228
- this.replace(parents[declaratorIndex + 2], expr);
229
- } else {
230
- this.replace(
231
- parents[declaratorIndex + 2],
232
- ExpressionStatement(expr)
233
- );
234
- }
235
- } else {
236
- this.replace(
237
- parents[declaratorIndex],
238
- VariableDeclarator(this.getPlaceholder(), expr)
239
- );
240
- }
241
- } else {
242
- if (parents[0].type == "FunctionDeclaration") {
243
- this.replace(
244
- parents[0],
245
- ExpressionStatement(
246
- AssignmentExpression("=", Identifier(newName), {
247
- ...parents[0],
248
- type: "FunctionExpression",
249
- id: null,
250
- })
251
- )
252
- );
253
- } else if (parents[0].type == "ClassDeclaration") {
254
- this.replace(
255
- parents[0],
256
- ExpressionStatement(
257
- AssignmentExpression("=", Identifier(newName), {
258
- ...parents[0],
259
- type: "ClassExpression",
260
- })
261
- )
262
- );
263
- }
264
- }
265
- });
266
- }
267
-
268
- if (defined.has(name)) {
269
- var lastRef = lastReferenceMap.get(name);
270
- var isDecommissioned = lastRef === i;
271
-
272
- if (isDecommissioned) {
273
- available.add(name);
274
- }
275
- }
276
- });
277
- });
278
- };
279
- }
280
- }