js-confuser 1.2.1 → 1.4.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 (94) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +7 -6
  3. package/dist/options.js +5 -1
  4. package/dist/parser.js +1 -2
  5. package/dist/presets.js +2 -2
  6. package/dist/transforms/calculator.js +48 -60
  7. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +482 -95
  8. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -0
  9. package/dist/transforms/controlFlowFlattening/{switchCaseObfucation.js → switchCaseObfuscation.js} +2 -2
  10. package/dist/transforms/deadCode.js +1 -1
  11. package/dist/transforms/dispatcher.js +14 -13
  12. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -10
  13. package/dist/transforms/flatten.js +5 -1
  14. package/dist/transforms/hideInitializingCode.js +17 -2
  15. package/dist/transforms/identifier/globalConcealing.js +46 -25
  16. package/dist/transforms/identifier/movedDeclarations.js +69 -68
  17. package/dist/transforms/identifier/renameVariables.js +22 -98
  18. package/dist/transforms/identifier/variableAnalysis.js +133 -0
  19. package/dist/transforms/label.js +11 -2
  20. package/dist/transforms/lock/antiDebug.js +32 -13
  21. package/dist/transforms/lock/lock.js +13 -2
  22. package/dist/transforms/minify.js +117 -120
  23. package/dist/transforms/opaquePredicates.js +4 -2
  24. package/dist/transforms/preparation/preparation.js +8 -0
  25. package/dist/transforms/renameLabels.js +17 -3
  26. package/dist/transforms/rgf.js +8 -3
  27. package/dist/transforms/shuffle.js +25 -9
  28. package/dist/transforms/stack.js +5 -9
  29. package/dist/transforms/string/encoding.js +209 -0
  30. package/dist/transforms/string/stringCompression.js +10 -10
  31. package/dist/transforms/string/stringConcealing.js +94 -65
  32. package/dist/transforms/string/stringSplitting.js +7 -7
  33. package/dist/transforms/transform.js +10 -0
  34. package/dist/traverse.js +1 -35
  35. package/dist/util/gen.js +3 -1
  36. package/dist/util/identifiers.js +9 -19
  37. package/dist/util/insert.js +6 -40
  38. package/dist/util/scope.js +17 -0
  39. package/package.json +2 -2
  40. package/src/options.ts +19 -3
  41. package/src/parser.ts +1 -2
  42. package/src/presets.ts +2 -2
  43. package/src/transforms/calculator.ts +87 -91
  44. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +742 -142
  45. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +6 -0
  46. package/src/transforms/controlFlowFlattening/{switchCaseObfucation.ts → switchCaseObfuscation.ts} +6 -2
  47. package/src/transforms/deadCode.ts +8 -0
  48. package/src/transforms/dispatcher.ts +29 -14
  49. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +43 -19
  50. package/src/transforms/flatten.ts +15 -2
  51. package/src/transforms/hideInitializingCode.ts +432 -406
  52. package/src/transforms/identifier/globalConcealing.ts +148 -46
  53. package/src/transforms/identifier/movedDeclarations.ts +78 -101
  54. package/src/transforms/identifier/renameVariables.ts +21 -96
  55. package/src/transforms/identifier/variableAnalysis.ts +124 -0
  56. package/src/transforms/label.ts +20 -2
  57. package/src/transforms/lock/antiDebug.ts +69 -26
  58. package/src/transforms/lock/lock.ts +37 -3
  59. package/src/transforms/minify.ts +154 -130
  60. package/src/transforms/opaquePredicates.ts +25 -3
  61. package/src/transforms/preparation/preparation.ts +8 -1
  62. package/src/transforms/renameLabels.ts +26 -3
  63. package/src/transforms/rgf.ts +6 -1
  64. package/src/transforms/shuffle.ts +87 -29
  65. package/src/transforms/stack.ts +6 -8
  66. package/src/transforms/string/encoding.ts +310 -0
  67. package/src/transforms/string/stringCompression.ts +37 -24
  68. package/src/transforms/string/stringConcealing.ts +157 -160
  69. package/src/transforms/string/stringSplitting.ts +12 -8
  70. package/src/transforms/transform.ts +15 -2
  71. package/src/traverse.ts +1 -31
  72. package/src/util/gen.ts +5 -3
  73. package/src/util/identifiers.ts +20 -20
  74. package/src/util/insert.ts +12 -78
  75. package/src/util/scope.ts +9 -0
  76. package/test/{transforms/compare.test.ts → compare.test.ts} +2 -2
  77. package/test/index.test.ts +109 -1
  78. package/test/templates/template.test.ts +14 -0
  79. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +392 -10
  80. package/test/transforms/dispatcher.test.ts +30 -0
  81. package/test/transforms/flatten.test.ts +28 -0
  82. package/test/transforms/hideInitializingCode.test.ts +336 -336
  83. package/test/transforms/identifier/globalConcealing.test.ts +1 -2
  84. package/test/transforms/identifier/movedDeclarations.test.ts +137 -112
  85. package/test/transforms/identifier/renameVariables.test.ts +124 -13
  86. package/test/transforms/lock/antiDebug.test.ts +43 -0
  87. package/test/transforms/lock/selfDefending.test.ts +68 -0
  88. package/test/transforms/minify.test.ts +137 -0
  89. package/test/transforms/renameLabels.test.ts +33 -0
  90. package/test/transforms/rgf.test.ts +29 -0
  91. package/test/transforms/string/stringSplitting.test.ts +33 -0
  92. package/test/util/identifiers.test.ts +105 -17
  93. package/dist/util/expr.js +0 -60
  94. package/src/util/expr.ts +0 -56
@@ -1,111 +1,30 @@
1
1
  import { ok } from "assert";
2
2
  import { ObfuscateOrder } from "../../order";
3
3
  import Template from "../../templates/template";
4
+ import { isBlock } from "../../traverse";
4
5
  import { isDirective } from "../../util/compare";
5
6
  import {
6
7
  ArrayExpression,
7
8
  CallExpression,
9
+ ConditionalExpression,
8
10
  FunctionDeclaration,
11
+ FunctionExpression,
9
12
  Identifier,
13
+ IfStatement,
10
14
  Literal,
11
15
  MemberExpression,
12
16
  Node,
13
17
  ReturnStatement,
18
+ SequenceExpression,
19
+ ThisExpression,
20
+ UpdateExpression,
14
21
  VariableDeclaration,
15
22
  VariableDeclarator,
16
23
  } from "../../util/gen";
17
- import { append, prepend } from "../../util/insert";
24
+ import { append, isLexContext, isVarContext, prepend } from "../../util/insert";
25
+ import { choice, getRandomInteger, getRandomString } from "../../util/random";
18
26
  import Transform from "../transform";
19
-
20
- /* eslint-disable @typescript-eslint/no-unused-expressions */
21
- function encode_ascii85(a) {
22
- var b, c, d, e, f, g, h, i, j, k;
23
- // @ts-ignore
24
- for (
25
- // @ts-ignore
26
- !/[^\x00-\xFF]/.test(a),
27
- b = "\x00\x00\x00\x00".slice(a.length % 4 || 4),
28
- a += b,
29
- c = [],
30
- d = 0,
31
- e = a.length;
32
- e > d;
33
- d += 4
34
- )
35
- (f =
36
- (a.charCodeAt(d) << 24) +
37
- (a.charCodeAt(d + 1) << 16) +
38
- (a.charCodeAt(d + 2) << 8) +
39
- a.charCodeAt(d + 3)),
40
- 0 !== f
41
- ? ((k = f % 85),
42
- (f = (f - k) / 85),
43
- (j = f % 85),
44
- (f = (f - j) / 85),
45
- (i = f % 85),
46
- (f = (f - i) / 85),
47
- (h = f % 85),
48
- (f = (f - h) / 85),
49
- (g = f % 85),
50
- c.push(g + 33, h + 33, i + 33, j + 33, k + 33))
51
- : c.push(122);
52
- return (
53
- (function (a, b) {
54
- for (var c = b; c > 0; c--) a.pop();
55
- })(c, b.length),
56
- "<~" + String.fromCharCode.apply(String, c) + "~>"
57
- );
58
- }
59
-
60
- function decode_ascii85(a) {
61
- var c,
62
- d,
63
- e,
64
- f,
65
- g,
66
- h = String,
67
- l = "length",
68
- w = 255,
69
- x = "charCodeAt",
70
- y = "slice",
71
- z = "replace";
72
- for (
73
- "<~" === a[y](0, 2) && "~>" === a[y](-2),
74
- a = a[y](2, -2)[z](/s/g, "")[z]("z", "!!!!!"),
75
- c = "uuuuu"[y](a[l] % 5 || 5),
76
- a += c,
77
- e = [],
78
- f = 0,
79
- g = a[l];
80
- g > f;
81
- f += 5
82
- )
83
- (d =
84
- 52200625 * (a[x](f) - 33) +
85
- 614125 * (a[x](f + 1) - 33) +
86
- 7225 * (a[x](f + 2) - 33) +
87
- 85 * (a[x](f + 3) - 33) +
88
- (a[x](f + 4) - 33)),
89
- e.push(w & (d >> 24), w & (d >> 16), w & (d >> 8), w & d);
90
- return (
91
- (function (a, b) {
92
- for (var c = b; c > 0; c--) a.pop();
93
- })(e, c[l]),
94
- h.fromCharCode.apply(h, e)
95
- );
96
- }
97
-
98
- var Ascii85Template = Template(`
99
- function {name}(a, LL = ["fromCharCode", "apply"]) {
100
- var c, d, e, f, g, h = String, l = "length", w = 255, x = "charCodeAt", y = "slice", z = "replace";
101
- for ("<~" === a[y](0, 2) && "~>" === a[y](-2), a = a[y](2, -2)[z](/\s/g, "")[z]("z", "!!!!!"),
102
- c = "uuuuu"[y](a[l] % 5 || 5), a += c, e = [], f = 0, g = a[l]; g > f; f += 5) d = 52200625 * (a[x](f) - 33) + 614125 * (a[x](f + 1) - 33) + 7225 * (a[x](f + 2) - 33) + 85 * (a[x](f + 3) - 33) + (a[x](f + 4) - 33),
103
- e.push(w & d >> 24, w & d >> 16, w & d >> 8, w & d);
104
- return function(a, b) {
105
- for (var c = b; c > 0; c--) a.pop();
106
- }(e, c[l]), h[LL[0]][LL[1]](h, e);
107
- }
108
- `);
27
+ import Encoding from "./encoding";
109
28
 
110
29
  export function isModuleSource(object: Node, parents: Node[]) {
111
30
  if (!parents[0]) {
@@ -140,83 +59,135 @@ export function isModuleSource(object: Node, parents: Node[]) {
140
59
  export default class StringConcealing extends Transform {
141
60
  arrayExpression: Node;
142
61
  set: Set<string>;
143
- index: { [str: string]: number };
62
+ index: { [str: string]: [number, string] };
144
63
 
145
- getterName = this.getPlaceholder();
146
64
  arrayName = this.getPlaceholder();
147
- decodeFn = this.getPlaceholder();
65
+ ignore = new Set<string>();
66
+ variablesMade = 1;
67
+ encoding: { [type: string]: string } = Object.create(null);
148
68
 
149
- decodeNode: Node;
69
+ hasAllEncodings: boolean;
150
70
 
151
71
  constructor(o) {
152
72
  super(o, ObfuscateOrder.StringConcealing);
153
73
 
154
74
  this.set = new Set();
155
75
  this.index = Object.create(null);
156
- }
76
+ this.arrayExpression = ArrayExpression([]);
77
+ this.hasAllEncodings = false;
157
78
 
158
- match(object, parents) {
159
- return (
160
- object.type == "Program" ||
161
- (object.type == "Literal" &&
162
- typeof object.value === "string" &&
163
- !isModuleSource(object, parents) &&
164
- !isDirective(object, parents)) //&&
165
- /*!parents.find((x) => x.$dispatcherSkip)*/
166
- );
79
+ // Pad array with useless strings
80
+ var dead = getRandomInteger(4, 10);
81
+ for (var i = 0; i < dead; i++) {
82
+ var str = getRandomString(getRandomInteger(4, 20));
83
+ var fn = this.transform(Literal(str), []);
84
+ if (fn) {
85
+ fn();
86
+ }
87
+ }
167
88
  }
168
89
 
169
- transform(object, parents) {
170
- if (object.type == "Program") {
171
- this.arrayExpression = ArrayExpression([]);
90
+ apply(tree) {
91
+ super.apply(tree);
92
+
93
+ var cacheName = this.getPlaceholder();
172
94
 
173
- return () => {
174
- var cacheName = this.getPlaceholder();
95
+ Object.keys(this.encoding).forEach((type) => {
96
+ var { template } = Encoding[type];
97
+ var decodeFn = this.getPlaceholder();
98
+ var getterFn = this.encoding[type];
175
99
 
176
- append(
177
- object,
178
- Template(`
179
-
180
- function ${this.getterName}(x, y, z){
181
- if ( z ) {
182
- return y[${cacheName}[z]] = x;
100
+ append(tree, template.single({ name: decodeFn }));
101
+
102
+ append(
103
+ tree,
104
+ Template(`
105
+
106
+ function ${getterFn}(x, y, z, a = ${decodeFn}, b = ${cacheName}){
107
+ if ( z ) {
108
+ return y[${cacheName}[z]] = ${getterFn}(x, y);
109
+ } else if ( y ) {
110
+ [b, y] = [a(b), x || z]
111
+ }
112
+
113
+ return y ? x[b[y]] : ${cacheName}[x] || (z=(b[x], a), ${cacheName}[x] = z(${this.arrayName}[x]))
183
114
  }
184
- return y ? x[${cacheName}[y]] : ${cacheName}[x] || (${cacheName}[x] = ${this.decodeFn}(${this.arrayName}[x]))
185
- }
115
+
116
+ `).single()
117
+ );
118
+ });
186
119
 
187
- `).single()
188
- );
120
+ var flowIntegrity = this.getPlaceholder();
189
121
 
190
- prepend(
191
- object,
192
- VariableDeclaration([
193
- VariableDeclarator(cacheName, ArrayExpression([])),
194
- VariableDeclarator(this.arrayName, this.arrayExpression),
195
- ])
196
- );
122
+ prepend(
123
+ tree,
124
+ VariableDeclaration([
125
+ VariableDeclarator(cacheName, ArrayExpression([])),
126
+ VariableDeclarator(flowIntegrity, Literal(0)),
127
+ VariableDeclarator(
128
+ this.arrayName,
129
+ CallExpression(
130
+ FunctionExpression(
131
+ [],
132
+ [
133
+ VariableDeclaration(
134
+ VariableDeclarator("a", this.arrayExpression)
135
+ ),
136
+ Template(
137
+ `return (${flowIntegrity} ? a.pop() : ${flowIntegrity}++, a)`
138
+ ).single(),
139
+ ]
140
+ ),
141
+ []
142
+ )
143
+ ),
144
+ ])
145
+ );
146
+ }
197
147
 
198
- append(
199
- object,
200
- (this.decodeNode = Ascii85Template.single({
201
- name: this.decodeFn,
202
- }))
203
- );
204
- };
205
- }
148
+ match(object, parents) {
149
+ return (
150
+ object.type == "Literal" &&
151
+ typeof object.value === "string" &&
152
+ object.value.length >= 3 &&
153
+ !isModuleSource(object, parents) &&
154
+ !isDirective(object, parents) //&&
155
+ /*!parents.find((x) => x.$dispatcherSkip)*/
156
+ );
157
+ }
206
158
 
159
+ transform(object: Node, parents: Node[]) {
207
160
  return () => {
208
- // No string concealing in the decoder function
209
- if (parents.find((x) => x == this.decodeNode)) {
161
+ // Empty strings are discarded
162
+ if (!object.value || this.ignore.has(object.value)) {
210
163
  return;
211
164
  }
212
165
 
213
- // Empty strings are discarded
214
- if (!object.value) {
215
- return;
166
+ var types = Object.keys(this.encoding);
167
+
168
+ var type = choice(types);
169
+ if (!type || (!this.hasAllEncodings && Math.random() > 0.9)) {
170
+ var allowed = Object.keys(Encoding).filter(
171
+ (type) => !this.encoding[type]
172
+ );
173
+
174
+ if (!allowed.length) {
175
+ this.hasAllEncodings = true;
176
+ } else {
177
+ var random = choice(allowed);
178
+ type = random;
179
+
180
+ this.encoding[random] = this.getPlaceholder();
181
+ }
216
182
  }
217
183
 
184
+ var fnName = this.encoding[type];
185
+ var encoder = Encoding[type];
186
+
218
187
  // The decode function must return correct result
219
- if (decode_ascii85(encode_ascii85(object.value)) != object.value) {
188
+ var encoded = encoder.encode(object.value);
189
+ if (encoder.decode(encoded) != object.value) {
190
+ this.ignore.add(object.value);
220
191
  this.warn(object.value.slice(0, 100));
221
192
  return;
222
193
  }
@@ -225,33 +196,59 @@ export default class StringConcealing extends Transform {
225
196
  if (object.value && object.value.length > 0) {
226
197
  var index = -1;
227
198
  if (!this.set.has(object.value)) {
228
- this.arrayExpression.elements.push(
229
- Literal(encode_ascii85(object.value))
230
- );
199
+ this.arrayExpression.elements.push(Literal(encoded));
231
200
  index = this.arrayExpression.elements.length - 1;
232
- this.index[object.value] = index;
201
+ this.index[object.value] = [index, fnName];
233
202
 
234
203
  this.set.add(object.value);
235
204
  } else {
236
- index = this.index[object.value];
205
+ [index, fnName] = this.index[object.value];
237
206
  ok(typeof index === "number");
238
207
  }
239
208
 
240
209
  ok(index != -1, "index == -1");
241
- this.replace(
242
- object,
243
- CallExpression(Identifier(this.getterName), [Literal(index)])
244
- );
245
210
 
246
- // Fix 2. Make parent property key computed
247
- if (
248
- parents[0] &&
249
- (parents[0].type == "Property" ||
250
- parents[0].type == "MethodDefinition") &&
251
- parents[0].key == object
252
- ) {
253
- parents[0].computed = true;
254
- parents[0].shorthand = false;
211
+ var callExpr = CallExpression(Identifier(fnName), [Literal(index)]);
212
+
213
+ // use `.apply` to fool automated de-obfuscators
214
+ if (Math.random() > 0.5) {
215
+ callExpr = CallExpression(
216
+ MemberExpression(Identifier(fnName), Identifier("apply"), false),
217
+ [ThisExpression(), ArrayExpression([Literal(index)])]
218
+ );
219
+ }
220
+
221
+ // use `.call`
222
+ else if (Math.random() > 0.5) {
223
+ callExpr = CallExpression(
224
+ MemberExpression(Identifier(fnName), Identifier("call"), false),
225
+ [ThisExpression(), Literal(index)]
226
+ );
227
+ }
228
+
229
+ var constantReference =
230
+ parents.length && Math.random() > 0.5 / this.variablesMade;
231
+
232
+ if (constantReference) {
233
+ // Define the string earlier, reference the name here
234
+
235
+ var name = this.getPlaceholder();
236
+
237
+ var place = choice(parents.filter((node) => isBlock(node)));
238
+ if (!place) {
239
+ this.error(Error("No lexical block to insert code"));
240
+ }
241
+
242
+ place.body.unshift(
243
+ VariableDeclaration(VariableDeclarator(name, callExpr))
244
+ );
245
+
246
+ this.replaceIdentifierOrLiteral(object, Identifier(name), parents);
247
+
248
+ this.variablesMade++;
249
+ } else {
250
+ // Direct call to the getter function
251
+ this.replaceIdentifierOrLiteral(object, callExpr, parents);
255
252
  }
256
253
  }
257
254
  };
@@ -6,6 +6,7 @@ import { ObfuscateOrder } from "../../order";
6
6
  import { isModuleSource } from "./stringConcealing";
7
7
  import { isDirective } from "../../util/compare";
8
8
  import { ok } from "assert";
9
+ import { ComputeProbabilityMap } from "../../probability";
9
10
 
10
11
  export default class StringSplitting extends Transform {
11
12
  joinPrototype: string;
@@ -59,13 +60,6 @@ export default class StringSplitting extends Transform {
59
60
 
60
61
  transform(object: Node, parents: Node[]) {
61
62
  return () => {
62
- var propIndex = parents.findIndex(
63
- (x) => x.type == "Property" || x.type == "MethodDefinition"
64
- );
65
- if (propIndex !== -1 && parents[propIndex].key == object) {
66
- parents[propIndex].computed = true;
67
- }
68
-
69
63
  var size = Math.round(
70
64
  Math.max(6, object.value.length / getRandomInteger(3, 8))
71
65
  );
@@ -78,6 +72,16 @@ export default class StringSplitting extends Transform {
78
72
  return;
79
73
  }
80
74
 
75
+ if (
76
+ !ComputeProbabilityMap(
77
+ this.options.stringSplitting,
78
+ (x) => x,
79
+ object.value
80
+ )
81
+ ) {
82
+ return;
83
+ }
84
+
81
85
  var binaryExpression;
82
86
  var parent;
83
87
  var last = chunks.pop();
@@ -101,7 +105,7 @@ export default class StringSplitting extends Transform {
101
105
 
102
106
  parent.right = Literal(last);
103
107
 
104
- this.replace(object, parent);
108
+ this.replaceIdentifierOrLiteral(object, parent, parents);
105
109
  };
106
110
  }
107
111
  }
@@ -1,4 +1,4 @@
1
- import traverse, { getDepth, getBlock, ExitCallback } from "../traverse";
1
+ import traverse, { ExitCallback } from "../traverse";
2
2
  import { AddComment, Node } from "../util/gen";
3
3
  import {
4
4
  alphabeticalGenerator,
@@ -6,7 +6,6 @@ import {
6
6
  getRandomInteger,
7
7
  } from "../util/random";
8
8
  import { ok } from "assert";
9
- import { isValidIdentifier } from "../util/compare";
10
9
  import Obfuscator from "../obfuscator";
11
10
  import { ObfuscateOptions } from "../options";
12
11
  import { ComputeProbabilityMap } from "../probability";
@@ -353,6 +352,20 @@ export default class Transform {
353
352
  this.objectAssign(node1, node2);
354
353
  }
355
354
 
355
+ replaceIdentifierOrLiteral(node1: Node, node2: Node, parents: Node[]) {
356
+ // Fix 2. Make parent property key computed
357
+ if (
358
+ parents[0] &&
359
+ (parents[0].type == "Property" ||
360
+ parents[0].type == "MethodDefinition") &&
361
+ parents[0].key == node1
362
+ ) {
363
+ parents[0].computed = true;
364
+ parents[0].shorthand = false;
365
+ }
366
+ this.replace(node1, node2);
367
+ }
368
+
356
369
  /**
357
370
  * Smartly merges two Nodes.
358
371
  * - Null checking
package/src/traverse.ts CHANGED
@@ -1,16 +1,6 @@
1
1
  import { Node } from "./util/gen";
2
2
  import { validateChain } from "./util/identifiers";
3
3
 
4
- /**
5
- * Returns all the scopes given parents array.
6
- * - `[object, ...parents]` is recommended.
7
- *
8
- * @param parents
9
- */
10
- export function getBlocks(parents: any[]): any[] {
11
- return parents.filter((x) => isBlock(x));
12
- }
13
-
14
4
  /**
15
5
  * A block refers to any object that has a **`.body`** property where code is nested.
16
6
  *
@@ -23,7 +13,7 @@ export function getBlock(object: any, parents: any[]) {
23
13
  if (!Array.isArray(parents)) {
24
14
  throw new Error("parents must be an array");
25
15
  }
26
- return getBlocks([object, ...parents])[0];
16
+ return [object, ...parents].find((node) => isBlock(node));
27
17
  }
28
18
 
29
19
  /**
@@ -40,26 +30,6 @@ export function isBlock(object: any) {
40
30
  );
41
31
  }
42
32
 
43
- /**
44
- * Returns a numerical representation of the depth.
45
- * - Depth is how many blocks nested.
46
- * - Program = 1 depth
47
- * - First Fn = 2 depth
48
- * - Nested Fn = 3 depth
49
- * - Second Fn = 2 depth
50
- * - etc...
51
- * @param object
52
- * @param parents
53
- */
54
- export function getDepth(object: any, parents: any[]) {
55
- if (!Array.isArray(parents)) {
56
- throw new Error("parents should be an array");
57
- }
58
- var scopes = getBlocks([object, ...parents].filter((x) => x));
59
-
60
- return scopes.length;
61
- }
62
-
63
33
  export type EnterCallback = (
64
34
  object: Node,
65
35
  parents: Node[]
package/src/util/gen.ts CHANGED
@@ -134,7 +134,9 @@ export function ThisExpression() {
134
134
  return { type: "ThisExpression" };
135
135
  }
136
136
 
137
- export function SwitchCase(test: any, consequent: any[]) {
137
+ export function SwitchCase(test: any, consequent: Node[]) {
138
+ ok(test === null || test);
139
+ ok(Array.isArray(consequent));
138
140
  return {
139
141
  type: "SwitchCase",
140
142
  test,
@@ -142,7 +144,7 @@ export function SwitchCase(test: any, consequent: any[]) {
142
144
  };
143
145
  }
144
146
 
145
- export function SwitchDefaultCase(consequent: any[]) {
147
+ export function SwitchDefaultCase(consequent: Node[]) {
146
148
  return SwitchCase(null, consequent);
147
149
  }
148
150
 
@@ -496,7 +498,7 @@ export function AssignmentPattern(left: Node, right: Node) {
496
498
  ok(left);
497
499
  ok(right);
498
500
  return {
499
- type: "AssignmentExpression",
501
+ type: "AssignmentPattern",
500
502
  left: left,
501
503
  right: right,
502
504
  };
@@ -30,17 +30,6 @@ export function validateChain(object: Node, parents: Node[]) {
30
30
  }
31
31
  }
32
32
 
33
- export function isWithinClass(object: Node, parents: Node[]) {
34
- return (
35
- isWithin(object, parents, "ClassDeclaration") ||
36
- isWithin(object, parents, "ClassExpression")
37
- );
38
- }
39
-
40
- export function isWithin(object: Node, parents: Node[], type: string): boolean {
41
- return [object, ...parents].some((x) => x.type == type);
42
- }
43
-
44
33
  /**
45
34
  * Returns detailed information about the given Identifier node.
46
35
  * @param object
@@ -117,15 +106,22 @@ export function getIdentifierInfo(object: Node, parents: Node[]) {
117
106
 
118
107
  var isFunctionCall = parent.callee == object; // NewExpression and CallExpression
119
108
 
109
+ var assignmentIndex = parents.findIndex(
110
+ (p) => p.type === "AssignmentExpression"
111
+ );
112
+
120
113
  var isAssignmentLeft =
121
- parent.type == "AssignmentExpression" && parent.left == object;
114
+ assignmentIndex !== -1 &&
115
+ parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object);
122
116
  var isAssignmentValue =
123
- parent.type == "AssignmentExpression" && parent.right == object;
117
+ assignmentIndex !== -1 &&
118
+ parents[assignmentIndex].right === (parents[assignmentIndex - 1] || object);
124
119
 
125
120
  var isUpdateExpression = parent.type == "UpdateExpression";
126
121
 
127
122
  var isClassDeclaration =
128
- parent.type == "ClassDeclaration" && parent.id == object;
123
+ (parent.type == "ClassDeclaration" || parent.type == "ClassExpression") &&
124
+ parent.id == object;
129
125
  var isMethodDefinition =
130
126
  parent.type == "MethodDefinition" &&
131
127
  parent.key == object &&
@@ -352,7 +348,7 @@ export function getDefiningIdentifier(object: Node, parents: Node[]): Location {
352
348
  }
353
349
  }
354
350
 
355
- export function isFunctionParameter(o: Node, p: Node[]) {
351
+ export function isFunctionParameter(o: Node, p: Node[], c?: Node) {
356
352
  ok(o);
357
353
  ok(p);
358
354
  validateChain(o, p);
@@ -365,7 +361,7 @@ export function isFunctionParameter(o: Node, p: Node[]) {
365
361
  return false;
366
362
  }
367
363
 
368
- var c = getVarContext(o, p);
364
+ c = c || getVarContext(o, p);
369
365
  if (c === object) {
370
366
  var pIndex = p.indexOf(object.params);
371
367
  if (pIndex == -1) {
@@ -376,8 +372,7 @@ export function isFunctionParameter(o: Node, p: Node[]) {
376
372
  var paramIndex = object.params.indexOf(param);
377
373
  ok(paramIndex !== -1);
378
374
 
379
- var sliced = p.slice(p.indexOf(paramIndex));
380
- ok(!sliced.includes(o));
375
+ var sliced = p.slice(0, pIndex);
381
376
 
382
377
  var isReferenced = true;
383
378
  var i = 0;
@@ -391,7 +386,12 @@ export function isFunctionParameter(o: Node, p: Node[]) {
391
386
  break;
392
387
  }
393
388
 
394
- if (node.type == "ObjectPattern" && node.key === down) {
389
+ if (
390
+ node.type == "Property" &&
391
+ node.key === down &&
392
+ sliced[i + 2] &&
393
+ sliced[i + 2].type == "ObjectPattern"
394
+ ) {
395
395
  isReferenced = false;
396
396
  break;
397
397
  }
@@ -419,7 +419,7 @@ export function getFunctionParameters(
419
419
 
420
420
  walk(object.params, [object, ...parents], (o, p) => {
421
421
  if (o.type == "Identifier") {
422
- if (isFunctionParameter(o, p)) {
422
+ if (isFunctionParameter(o, p, object)) {
423
423
  locations.push([o, p]);
424
424
  }
425
425
  }