js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.3

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 (78) hide show
  1. package/CHANGELOG.md +24 -6
  2. package/dist/constants.js +6 -2
  3. package/dist/index.js +12 -0
  4. package/dist/obfuscator.js +117 -6
  5. package/dist/order.js +0 -1
  6. package/dist/probability.js +1 -96
  7. package/dist/templates/getGlobalTemplate.js +4 -1
  8. package/dist/templates/stringCompressionTemplate.js +3 -3
  9. package/dist/templates/tamperProtectionTemplates.js +1 -1
  10. package/dist/templates/template.js +17 -12
  11. package/dist/transforms/controlFlowFlattening.js +2 -6
  12. package/dist/transforms/deadCode.js +8 -15
  13. package/dist/transforms/dispatcher.js +1 -2
  14. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -0
  15. package/dist/transforms/extraction/objectExtraction.js +1 -2
  16. package/dist/transforms/finalizer.js +1 -1
  17. package/dist/transforms/flatten.js +2 -19
  18. package/dist/transforms/identifier/globalConcealing.js +1 -2
  19. package/dist/transforms/identifier/movedDeclarations.js +12 -5
  20. package/dist/transforms/identifier/renameVariables.js +7 -6
  21. package/dist/transforms/lock/lock.js +9 -2
  22. package/dist/transforms/minify.js +14 -1
  23. package/dist/transforms/opaquePredicates.js +5 -6
  24. package/dist/transforms/pack.js +5 -0
  25. package/dist/transforms/plugin.js +20 -39
  26. package/dist/transforms/renameLabels.js +1 -2
  27. package/dist/transforms/rgf.js +29 -11
  28. package/dist/transforms/shuffle.js +10 -11
  29. package/dist/transforms/string/stringCompression.js +14 -10
  30. package/dist/transforms/string/stringConcealing.js +4 -4
  31. package/dist/transforms/string/stringEncoding.js +4 -2
  32. package/dist/transforms/string/stringSplitting.js +4 -2
  33. package/dist/transforms/variableMasking.js +1 -2
  34. package/dist/utils/NameGen.js +3 -2
  35. package/dist/utils/PredicateGen.js +62 -0
  36. package/dist/utils/ast-utils.js +24 -9
  37. package/dist/validateOptions.js +2 -2
  38. package/package.json +2 -2
  39. package/src/constants.ts +6 -5
  40. package/src/index.ts +1 -0
  41. package/src/obfuscator.ts +148 -7
  42. package/src/options.ts +14 -6
  43. package/src/order.ts +0 -2
  44. package/src/probability.ts +0 -110
  45. package/src/templates/getGlobalTemplate.ts +5 -1
  46. package/src/templates/stringCompressionTemplate.ts +4 -28
  47. package/src/templates/tamperProtectionTemplates.ts +7 -3
  48. package/src/templates/template.ts +5 -3
  49. package/src/transforms/controlFlowFlattening.ts +2 -7
  50. package/src/transforms/deadCode.ts +11 -23
  51. package/src/transforms/dispatcher.ts +1 -2
  52. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +10 -1
  53. package/src/transforms/extraction/objectExtraction.ts +1 -2
  54. package/src/transforms/finalizer.ts +1 -1
  55. package/src/transforms/flatten.ts +3 -22
  56. package/src/transforms/identifier/globalConcealing.ts +4 -2
  57. package/src/transforms/identifier/movedDeclarations.ts +18 -6
  58. package/src/transforms/identifier/renameVariables.ts +10 -6
  59. package/src/transforms/lock/lock.ts +14 -3
  60. package/src/transforms/minify.ts +24 -2
  61. package/src/transforms/opaquePredicates.ts +5 -8
  62. package/src/transforms/pack.ts +6 -0
  63. package/src/transforms/plugin.ts +47 -69
  64. package/src/transforms/renameLabels.ts +1 -2
  65. package/src/transforms/rgf.ts +39 -14
  66. package/src/transforms/shuffle.ts +28 -26
  67. package/src/transforms/string/encoding.ts +1 -1
  68. package/src/transforms/string/stringCompression.ts +22 -13
  69. package/src/transforms/string/stringConcealing.ts +11 -7
  70. package/src/transforms/string/stringEncoding.ts +6 -2
  71. package/src/transforms/string/stringSplitting.ts +9 -4
  72. package/src/transforms/variableMasking.ts +1 -2
  73. package/src/utils/NameGen.ts +4 -2
  74. package/src/utils/PredicateGen.ts +61 -0
  75. package/src/utils/ast-utils.ts +16 -9
  76. package/src/validateOptions.ts +7 -4
  77. package/src/transforms/functionOutlining.ts +0 -225
  78. package/src/utils/ControlObject.ts +0 -141
@@ -4,7 +4,6 @@ import * as t from "@babel/types";
4
4
  import Template from "../templates/template";
5
5
  import { ok } from "assert";
6
6
  import { chance, getRandomString } from "../utils/random-utils";
7
- import { computeProbabilityMap } from "../probability";
8
7
  import { Order } from "../order";
9
8
  import { NodeSymbol, PREDICTABLE, UNSAFE } from "../constants";
10
9
  import {
@@ -146,7 +145,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
146
145
  }
147
146
 
148
147
  for (var name of functionPaths.keys()) {
149
- if (!computeProbabilityMap(me.options.dispatcher, name)) {
148
+ if (!me.computeProbabilityMap(me.options.dispatcher, name)) {
150
149
  functionPaths.delete(name);
151
150
  }
152
151
  }
@@ -2,7 +2,11 @@ import * as t from "@babel/types";
2
2
  import { ok } from "assert";
3
3
  import { PluginArg, PluginObject } from "../plugin";
4
4
  import { Order } from "../../order";
5
- import { ensureComputedExpression, prepend } from "../../utils/ast-utils";
5
+ import {
6
+ ensureComputedExpression,
7
+ isModuleImport,
8
+ prepend,
9
+ } from "../../utils/ast-utils";
6
10
  import { createLiteral, LiteralValue, numericLiteral } from "../../utils/node";
7
11
  import { NodePath } from "@babel/traverse";
8
12
 
@@ -49,6 +53,11 @@ export default ({ Plugin }: PluginArg): PluginObject => {
49
53
  t.Literal | t.Identifier
50
54
  >;
51
55
 
56
+ // Don't change module imports
57
+ if (literalPath.isStringLiteral()) {
58
+ if (isModuleImport(literalPath)) return;
59
+ }
60
+
52
61
  let node = literalPath.node;
53
62
  var isUndefined = false;
54
63
  if (literalPath.isIdentifier()) {
@@ -7,7 +7,6 @@ import {
7
7
  getObjectPropertyAsString,
8
8
  getParentFunctionOrProgram,
9
9
  } from "../../utils/ast-utils";
10
- import { computeProbabilityMap } from "../../probability";
11
10
 
12
11
  export default ({ Plugin }: PluginArg): PluginObject => {
13
12
  const me = Plugin(Order.ObjectExtraction, {
@@ -152,7 +151,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
152
151
  if (!isObjectSafe) return;
153
152
 
154
153
  if (
155
- !computeProbabilityMap(
154
+ !me.computeProbabilityMap(
156
155
  me.options.objectExtraction,
157
156
  identifier.node.name
158
157
  )
@@ -41,7 +41,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
41
41
  }),
42
42
 
43
43
  // Hexadecimal numbers
44
- NumberLiteral: {
44
+ NumericLiteral: {
45
45
  exit(path) {
46
46
  if (me.options.hexadecimalNumbers) {
47
47
  const { value } = path.node;
@@ -11,7 +11,6 @@ import {
11
11
  prependProgram,
12
12
  } from "../utils/ast-utils";
13
13
  import { PluginArg, PluginObject } from "./plugin";
14
- import { computeProbabilityMap } from "../probability";
15
14
  import { Order } from "../order";
16
15
  import { NodeSymbol, PREDICTABLE, UNSAFE } from "../constants";
17
16
  import {
@@ -58,7 +57,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
58
57
  functionName = "anonymous";
59
58
  }
60
59
 
61
- if (!computeProbabilityMap(me.options.flatten, functionName)) {
60
+ if (!me.computeProbabilityMap(me.options.flatten, functionName)) {
62
61
  return;
63
62
  }
64
63
 
@@ -117,26 +116,8 @@ export default ({ Plugin }: PluginArg): PluginObject => {
117
116
  return;
118
117
  }
119
118
 
120
- var definedLocal = identifierPath.scope;
121
- do {
122
- if (definedLocal.hasOwnBinding(identifierName)) return;
123
- if (definedLocal === fnPath.scope) break;
124
-
125
- definedLocal = definedLocal.parent;
126
- if (definedLocal === program.scope)
127
- ok(functionName + ":" + identifierName);
128
- } while (definedLocal);
129
-
130
- var cursor: Scope = fnPath.scope.parent;
131
- var isOutsideVariable = false;
132
-
133
- do {
134
- if (cursor.hasBinding(identifierName)) {
135
- isOutsideVariable = true;
136
- break;
137
- }
138
- cursor = cursor.parent;
139
- } while (cursor);
119
+ var isOutsideVariable =
120
+ fnPath.scope.parent.getBinding(identifierName) === binding;
140
121
 
141
122
  if (!isOutsideVariable) {
142
123
  return;
@@ -4,7 +4,6 @@ import { NameGen } from "../../utils/NameGen";
4
4
  import Template from "../../templates/template";
5
5
  import { PluginArg, PluginObject } from "../plugin";
6
6
  import { Order } from "../../order";
7
- import { computeProbabilityMap } from "../../probability";
8
7
  import {
9
8
  MULTI_TRANSFORM,
10
9
  reservedIdentifiers,
@@ -132,7 +131,10 @@ export default ({ Plugin }: PluginArg): PluginObject => {
132
131
  if (!mapping) {
133
132
  // Allow user to disable custom global variables
134
133
  if (
135
- !computeProbabilityMap(me.options.globalConcealing, globalName)
134
+ !me.computeProbabilityMap(
135
+ me.options.globalConcealing,
136
+ globalName
137
+ )
136
138
  )
137
139
  continue;
138
140
 
@@ -65,8 +65,12 @@ export default ({ Plugin }: PluginArg): PluginObject => {
65
65
  if (!functionPath || !(functionPath.node as NodeSymbol)[PREDICTABLE])
66
66
  return;
67
67
 
68
+ var fnBody = functionPath.get("body");
69
+
70
+ if (!fnBody.isBlockStatement()) return;
71
+
68
72
  // Must be direct child of the function
69
- if (path.parentPath !== functionPath.get("body")) return;
73
+ if (path.parentPath !== fnBody) return;
70
74
 
71
75
  const functionName = path.node.id.name;
72
76
 
@@ -99,7 +103,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
99
103
  }
100
104
 
101
105
  prepend(
102
- functionPath,
106
+ fnBody,
103
107
  new Template(`
104
108
  if(!${functionName}) {
105
109
  ${functionName} = {functionExpression};
@@ -113,6 +117,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
113
117
  },
114
118
  VariableDeclaration: {
115
119
  exit(path) {
120
+ if (me.isSkipped(path)) return;
116
121
  if (path.node.kind !== "var") return;
117
122
  if (path.node.declarations.length !== 1) return;
118
123
 
@@ -150,7 +155,11 @@ export default ({ Plugin }: PluginArg): PluginObject => {
150
155
  let isDefinedAtTop = false;
151
156
  const parentPath = path.parentPath;
152
157
  if (parentPath.isBlock()) {
153
- isDefinedAtTop = parentPath.get("body").indexOf(path) === 0;
158
+ isDefinedAtTop =
159
+ parentPath
160
+ .get("body")
161
+ .filter((x) => x.type !== "ImportDeclaration")
162
+ .indexOf(path) === 0;
154
163
  }
155
164
 
156
165
  // Already at the top - nothing will change
@@ -214,7 +223,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
214
223
  path.isBlock()
215
224
  ) as NodePath<t.Block>;
216
225
 
217
- var topNode = block.node.body[0];
226
+ var topNode = block.node.body.filter(
227
+ (x) => x.type !== "ImportDeclaration"
228
+ )[0];
218
229
  const variableDeclarator = t.variableDeclarator(
219
230
  t.identifier(name)
220
231
  );
@@ -223,8 +234,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
223
234
  topNode.declarations.push(variableDeclarator);
224
235
  break;
225
236
  } else {
226
- block.node.body.unshift(
227
- t.variableDeclaration("var", [variableDeclarator])
237
+ prepend(
238
+ block,
239
+ me.skip(t.variableDeclaration("var", [variableDeclarator]))
228
240
  );
229
241
  }
230
242
 
@@ -6,9 +6,7 @@ import { Order } from "../../order";
6
6
  import {
7
7
  noRenameVariablePrefix,
8
8
  placeholderVariablePrefix,
9
- variableFunctionName,
10
9
  } from "../../constants";
11
- import { computeProbabilityMap } from "../../probability";
12
10
  import {
13
11
  getParentFunctionOrProgram,
14
12
  isDefiningIdentifier,
@@ -215,19 +213,25 @@ export default ({ Plugin }: PluginArg): PluginObject => {
215
213
  // Placeholder variables should always be renamed
216
214
  if (name.startsWith(placeholderVariablePrefix)) return true;
217
215
 
218
- // Do not rename exports
219
- if (isExportedIdentifier(bindings?.get(name))) return false;
216
+ const binding = bindings?.get(name);
217
+
218
+ if (binding) {
219
+ // Do not rename exports
220
+ if (isExportedIdentifier(binding)) return false;
221
+ }
220
222
 
221
223
  if (name === me.obfuscator.getStringCompressionLibraryName())
222
224
  return false;
223
225
 
224
226
  // Global variables are additionally checked against user option
225
227
  if (isGlobal) {
226
- if (!computeProbabilityMap(me.options.renameGlobals, name))
228
+ if (!me.computeProbabilityMap(me.options.renameGlobals, name))
227
229
  return false;
228
230
  }
229
231
 
230
- if (!computeProbabilityMap(me.options.renameVariables, name, isGlobal))
232
+ if (
233
+ !me.computeProbabilityMap(me.options.renameVariables, name, isGlobal)
234
+ )
231
235
  return false;
232
236
 
233
237
  return true;
@@ -26,7 +26,6 @@ import {
26
26
  NativeFunctionTemplate,
27
27
  StrictModeTemplate,
28
28
  } from "../../templates/tamperProtectionTemplates";
29
- import { computeProbabilityMap } from "../../probability";
30
29
 
31
30
  export default ({ Plugin }: PluginArg): PluginObject => {
32
31
  const me = Plugin(Order.Lock, {
@@ -36,6 +35,11 @@ export default ({ Plugin }: PluginArg): PluginObject => {
36
35
  });
37
36
 
38
37
  if (me.options.lock.startDate instanceof Date) {
38
+ // Ensure date is in the past
39
+ if (me.options.lock.startDate.getTime() > Date.now()) {
40
+ me.warn("lock.startDate is detected to be in the future");
41
+ }
42
+
39
43
  me.options.lock.customLocks.push({
40
44
  code: [
41
45
  `
@@ -54,6 +58,11 @@ export default ({ Plugin }: PluginArg): PluginObject => {
54
58
  }
55
59
 
56
60
  if (me.options.lock.endDate instanceof Date) {
61
+ // Ensure date is in the future
62
+ if (me.options.lock.endDate.getTime() < Date.now()) {
63
+ me.warn("lock.endDate is detected to be in the past");
64
+ }
65
+
57
66
  me.options.lock.customLocks.push({
58
67
  code: [
59
68
  `
@@ -127,7 +136,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
127
136
  const timesMap = new WeakMap<CustomLock, number>();
128
137
 
129
138
  let countermeasuresNode: NodePath<t.Identifier>;
130
- let invokeCountermeasuresFnName;
139
+ let invokeCountermeasuresFnName: string;
131
140
 
132
141
  if (me.options.lock.countermeasures) {
133
142
  invokeCountermeasuresFnName = me.getPlaceholder("invokeCountermeasures");
@@ -356,7 +365,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
356
365
  // Don't apply to invokeCountermeasures function (Intended)
357
366
  if (me.obfuscator.isInternalVariable(functionName)) return;
358
367
 
359
- if (!computeProbabilityMap(me.options.lock.integrity, functionName))
368
+ if (
369
+ !me.computeProbabilityMap(me.options.lock.integrity, functionName)
370
+ )
360
371
  return;
361
372
 
362
373
  var newFnName = me.getPlaceholder();
@@ -8,7 +8,12 @@ import {
8
8
  isUndefined,
9
9
  } from "../utils/ast-utils";
10
10
  import { Binding, Scope } from "@babel/traverse";
11
- import { NodeSymbol, placeholderVariablePrefix, UNSAFE } from "../constants";
11
+ import {
12
+ NO_REMOVE,
13
+ NodeSymbol,
14
+ placeholderVariablePrefix,
15
+ UNSAFE,
16
+ } from "../constants";
12
17
 
13
18
  const identifierMap = new Map<string, () => t.Expression>();
14
19
  identifierMap.set("undefined", () =>
@@ -120,6 +125,19 @@ export default ({ Plugin }: PluginArg): PluginObject => {
120
125
  }
121
126
  },
122
127
  },
128
+ // "a" + "b" -> "ab"
129
+ BinaryExpression: {
130
+ exit(path) {
131
+ if (path.node.operator !== "+") return;
132
+
133
+ const left = path.get("left");
134
+ const right = path.get("right");
135
+
136
+ if (!left.isStringLiteral() || !right.isStringLiteral()) return;
137
+
138
+ path.replaceWith(t.stringLiteral(left.node.value + right.node.value));
139
+ },
140
+ },
123
141
  // a["key"] -> a.key
124
142
  MemberExpression: {
125
143
  exit(path) {
@@ -215,7 +233,8 @@ export default ({ Plugin }: PluginArg): PluginObject => {
215
233
  const id = path.get("id");
216
234
  if (
217
235
  id.isIdentifier() &&
218
- !id.node.name.startsWith(placeholderVariablePrefix)
236
+ !id.node.name.startsWith(placeholderVariablePrefix) &&
237
+ !(path.node as NodeSymbol)[NO_REMOVE]
219
238
  ) {
220
239
  const binding = path.scope.getBinding(id.node.name);
221
240
  if (
@@ -285,6 +304,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
285
304
  const fn = getParentFunctionOrProgram(path);
286
305
  if ((fn.node as NodeSymbol)[UNSAFE]) return;
287
306
 
307
+ // Node explicitly marked as not to be removed
308
+ if ((id as NodeSymbol)[NO_REMOVE]) return;
309
+
288
310
  const binding = path.scope.getBinding(id.node.name);
289
311
 
290
312
  if (
@@ -2,9 +2,8 @@ import { PluginArg, PluginObject } from "./plugin";
2
2
  import { Order } from "../order";
3
3
  import { NodePath } from "@babel/traverse";
4
4
  import * as t from "@babel/types";
5
- import { getBlock } from "../utils/ast-utils";
6
5
  import { chance, getRandomString } from "../utils/random-utils";
7
- import { computeProbabilityMap } from "../probability";
6
+ import PredicateGen from "../utils/PredicateGen";
8
7
 
9
8
  export default ({ Plugin }: PluginArg): PluginObject => {
10
9
  const me = Plugin(Order.OpaquePredicates, {
@@ -13,12 +12,10 @@ export default ({ Plugin }: PluginArg): PluginObject => {
13
12
  },
14
13
  });
15
14
 
16
- function createTruePredicate(path: NodePath) {
17
- const controlObject = me.getControlObject(getBlock(path));
18
-
19
- var trueValue = controlObject.createTruePredicate();
15
+ const predicateGen = new PredicateGen(me);
20
16
 
21
- return trueValue;
17
+ function createTruePredicate(path: NodePath) {
18
+ return predicateGen.generateTrueExpression(path);
22
19
  }
23
20
 
24
21
  let active = true;
@@ -27,7 +24,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
27
24
  if (!active) return false;
28
25
  if (path.find((p) => me.isSkipped(p))) return false;
29
26
 
30
- if (!computeProbabilityMap(me.options.opaquePredicates)) return false;
27
+ if (!me.computeProbabilityMap(me.options.opaquePredicates)) return false;
31
28
 
32
29
  transformCount++;
33
30
 
@@ -55,8 +55,14 @@ export default function pack({ Plugin }: PluginArg): PluginObject {
55
55
  if (reservedIdentifiers.has(identifierName)) return;
56
56
  if (me.obfuscator.options.globalVariables.has(identifierName)) return;
57
57
  if (identifierName === variableFunctionName) return;
58
+ if (identifierName === objectName) return;
58
59
 
59
60
  if (!path.scope.hasGlobal(identifierName)) return;
61
+ if (path.scope.hasBinding(identifierName)) return;
62
+
63
+ // Check user's custom implementation
64
+ if (!me.computeProbabilityMap(me.options.pack, identifierName))
65
+ return;
60
66
 
61
67
  if (
62
68
  path.key === "argument" &&
@@ -1,13 +1,11 @@
1
1
  import { NodePath, Visitor } from "@babel/traverse";
2
2
  import Obfuscator from "../obfuscator";
3
- import { chance, choice, getRandomString } from "../utils/random-utils";
3
+ import { getRandomString } from "../utils/random-utils";
4
4
  import { Order } from "../order";
5
5
  import * as t from "@babel/types";
6
- import { FN_LENGTH, NodeSymbol, SKIP, CONTROL_OBJECTS } from "../constants";
6
+ import { FN_LENGTH, NodeSymbol, SKIP } from "../constants";
7
7
  import { SetFunctionLengthTemplate } from "../templates/setFunctionLengthTemplate";
8
8
  import { prepend, prependProgram } from "../utils/ast-utils";
9
- import ControlObject from "../utils/ControlObject";
10
- import { ok } from "assert";
11
9
  import { numericLiteral } from "../utils/node";
12
10
 
13
11
  export interface PluginObject {
@@ -30,9 +28,14 @@ export class PluginInstance {
30
28
  constructor(
31
29
  public pluginOptions: { name?: string; order?: number },
32
30
  public obfuscator: Obfuscator
33
- ) {}
31
+ ) {
32
+ this.computeProbabilityMap = obfuscator.computeProbabilityMap.bind(
33
+ this.obfuscator
34
+ );
35
+ }
34
36
 
35
37
  public changeData: { [key: string]: number } = {};
38
+ public computeProbabilityMap: Obfuscator["computeProbabilityMap"];
36
39
 
37
40
  get name() {
38
41
  return this.pluginOptions.name || "unnamed";
@@ -74,43 +77,48 @@ export class PluginInstance {
74
77
  setFunctionLength(path: NodePath<t.Function>, originalLength: number) {
75
78
  (path.node as NodeSymbol)[FN_LENGTH] = originalLength;
76
79
 
77
- // Function length
78
- if (this.options.preserveFunctionLength && originalLength > 0) {
79
- if (!this.setFunctionLengthName) {
80
- this.setFunctionLengthName = this.getPlaceholder("fnLength");
81
-
82
- this.skip(
83
- prependProgram(
84
- path,
85
- SetFunctionLengthTemplate.compile({
86
- fnName: this.setFunctionLengthName,
87
- })
88
- )
89
- );
90
- }
91
- if (t.isFunctionDeclaration(path.node)) {
92
- prepend(
93
- path.parentPath,
94
- t.expressionStatement(
95
- t.callExpression(t.identifier(this.setFunctionLengthName), [
96
- t.identifier(path.node.id.name),
97
- numericLiteral(originalLength),
98
- ])
99
- )
100
- );
101
- } else if (
102
- t.isFunctionExpression(path.node) ||
103
- t.isArrowFunctionExpression(path.node)
104
- ) {
105
- path.replaceWith(
80
+ // Skip if user disabled this feature
81
+ if (!this.options.preserveFunctionLength) return;
82
+
83
+ // Skip if function has no parameters
84
+ if (originalLength === 0) return;
85
+
86
+ // Create the function length setter if it doesn't exist
87
+ if (!this.setFunctionLengthName) {
88
+ this.setFunctionLengthName = this.getPlaceholder("fnLength");
89
+
90
+ this.skip(
91
+ prependProgram(
92
+ path,
93
+ SetFunctionLengthTemplate.compile({
94
+ fnName: this.setFunctionLengthName,
95
+ })
96
+ )
97
+ );
98
+ }
99
+
100
+ if (t.isFunctionDeclaration(path.node)) {
101
+ prepend(
102
+ path.parentPath,
103
+ t.expressionStatement(
106
104
  t.callExpression(t.identifier(this.setFunctionLengthName), [
107
- path.node,
105
+ t.identifier(path.node.id.name),
108
106
  numericLiteral(originalLength),
109
107
  ])
110
- );
111
- } else {
112
- // TODO
113
- }
108
+ )
109
+ );
110
+ } else if (
111
+ t.isFunctionExpression(path.node) ||
112
+ t.isArrowFunctionExpression(path.node)
113
+ ) {
114
+ path.replaceWith(
115
+ t.callExpression(t.identifier(this.setFunctionLengthName), [
116
+ path.node,
117
+ numericLiteral(originalLength),
118
+ ])
119
+ );
120
+ } else {
121
+ // TODO
114
122
  }
115
123
  }
116
124
 
@@ -125,36 +133,6 @@ export class PluginInstance {
125
133
  return "__p_" + getRandomString(4) + (suffix ? "_" + suffix : "");
126
134
  }
127
135
 
128
- /**
129
- * Retrieves (or creates) a `ControlObject` for the given `blockPath`.
130
- */
131
- getControlObject(blockPath: NodePath<t.Block>, createMultiple = true) {
132
- ok(blockPath.isBlock());
133
-
134
- var controlObjects = (blockPath.node as NodeSymbol)[CONTROL_OBJECTS];
135
- if (!controlObjects) {
136
- controlObjects = [];
137
- }
138
-
139
- if (
140
- controlObjects.length === 0 ||
141
- (createMultiple &&
142
- chance(
143
- controlObjects[0].propertyNames.size - 15 * controlObjects.length
144
- ))
145
- ) {
146
- var newControlObject = new ControlObject(this, blockPath);
147
-
148
- controlObjects.push(newControlObject);
149
-
150
- (blockPath.node as NodeSymbol)[CONTROL_OBJECTS] = controlObjects;
151
-
152
- return newControlObject;
153
- }
154
-
155
- return choice(controlObjects);
156
- }
157
-
158
136
  /**
159
137
  * Logs a message to the console, only if `verbose` is enabled.
160
138
  * @param messages
@@ -4,7 +4,6 @@ import { PluginArg, PluginObject } from "./plugin";
4
4
  import { Order } from "../order";
5
5
  import { NameGen } from "../utils/NameGen";
6
6
  import { ok } from "assert";
7
- import { computeProbabilityMap } from "../probability";
8
7
 
9
8
  const LABEL = Symbol("label");
10
9
 
@@ -127,7 +126,7 @@ export default function ({ Plugin }: PluginArg): PluginObject {
127
126
  if (isRequired) {
128
127
  var newName = labelInterface.label;
129
128
  if (
130
- computeProbabilityMap(
129
+ me.computeProbabilityMap(
131
130
  me.options.renameLabels,
132
131
  labelInterface.label
133
132
  )