js-confuser 1.5.8 → 1.6.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 (139) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +69 -0
  3. package/README.md +143 -7
  4. package/dist/index.js +33 -4
  5. package/dist/obfuscator.js +30 -31
  6. package/dist/options.js +4 -5
  7. package/dist/order.js +4 -6
  8. package/dist/probability.js +2 -4
  9. package/dist/templates/bufferToString.js +13 -0
  10. package/dist/templates/crash.js +2 -2
  11. package/dist/templates/es5.js +18 -0
  12. package/dist/transforms/antiTooling.js +1 -1
  13. package/dist/transforms/calculator.js +77 -21
  14. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  15. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
  16. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  17. package/dist/transforms/deadCode.js +33 -25
  18. package/dist/transforms/dispatcher.js +7 -6
  19. package/dist/transforms/es5/antiClass.js +6 -2
  20. package/dist/transforms/es5/antiDestructuring.js +3 -1
  21. package/dist/transforms/es5/es5.js +31 -34
  22. package/dist/transforms/eval.js +11 -0
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
  24. package/dist/transforms/extraction/objectExtraction.js +6 -1
  25. package/dist/transforms/finalizer.js +82 -0
  26. package/dist/transforms/flatten.js +82 -55
  27. package/dist/transforms/hexadecimalNumbers.js +34 -9
  28. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  29. package/dist/transforms/identifier/globalConcealing.js +10 -83
  30. package/dist/transforms/identifier/movedDeclarations.js +2 -8
  31. package/dist/transforms/identifier/renameVariables.js +39 -27
  32. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  33. package/dist/transforms/minify.js +80 -61
  34. package/dist/transforms/opaquePredicates.js +1 -1
  35. package/dist/transforms/preparation/preparation.js +2 -2
  36. package/dist/transforms/preparation.js +231 -0
  37. package/dist/transforms/renameLabels.js +1 -1
  38. package/dist/transforms/rgf.js +4 -5
  39. package/dist/transforms/stack.js +87 -26
  40. package/dist/transforms/string/encoding.js +150 -179
  41. package/dist/transforms/string/stringCompression.js +14 -15
  42. package/dist/transforms/string/stringConcealing.js +25 -8
  43. package/dist/transforms/string/stringEncoding.js +13 -24
  44. package/dist/transforms/transform.js +11 -18
  45. package/dist/traverse.js +24 -18
  46. package/dist/util/compare.js +2 -2
  47. package/dist/util/gen.js +15 -0
  48. package/dist/util/insert.js +31 -7
  49. package/dist/util/random.js +15 -0
  50. package/package.json +5 -5
  51. package/src/index.ts +57 -19
  52. package/src/obfuscator.ts +26 -29
  53. package/src/options.ts +17 -21
  54. package/src/order.ts +4 -8
  55. package/src/probability.ts +2 -3
  56. package/src/templates/bufferToString.ts +68 -0
  57. package/src/templates/crash.ts +5 -9
  58. package/src/templates/es5.ts +131 -0
  59. package/src/transforms/antiTooling.ts +1 -1
  60. package/src/transforms/calculator.ts +122 -59
  61. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  62. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
  63. package/src/transforms/deadCode.ts +383 -26
  64. package/src/transforms/dispatcher.ts +8 -6
  65. package/src/transforms/es5/antiClass.ts +10 -1
  66. package/src/transforms/es5/antiDestructuring.ts +3 -1
  67. package/src/transforms/es5/es5.ts +32 -77
  68. package/src/transforms/eval.ts +18 -0
  69. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
  70. package/src/transforms/extraction/objectExtraction.ts +12 -5
  71. package/src/transforms/finalizer.ts +75 -0
  72. package/src/transforms/flatten.ts +194 -151
  73. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  74. package/src/transforms/identifier/globalConcealing.ts +14 -103
  75. package/src/transforms/identifier/movedDeclarations.ts +4 -11
  76. package/src/transforms/identifier/renameVariables.ts +37 -30
  77. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  78. package/src/transforms/minify.ts +116 -77
  79. package/src/transforms/opaquePredicates.ts +2 -2
  80. package/src/transforms/preparation.ts +238 -0
  81. package/src/transforms/renameLabels.ts +2 -2
  82. package/src/transforms/rgf.ts +6 -7
  83. package/src/transforms/stack.ts +97 -37
  84. package/src/transforms/string/encoding.ts +115 -212
  85. package/src/transforms/string/stringCompression.ts +27 -18
  86. package/src/transforms/string/stringConcealing.ts +41 -11
  87. package/src/transforms/string/stringEncoding.ts +18 -18
  88. package/src/transforms/transform.ts +15 -21
  89. package/src/traverse.ts +24 -12
  90. package/src/types.ts +11 -2
  91. package/src/util/compare.ts +2 -2
  92. package/src/util/gen.ts +21 -1
  93. package/src/util/insert.ts +49 -9
  94. package/src/util/random.ts +13 -0
  95. package/test/code/Cash.test.ts +1 -1
  96. package/test/code/Dynamic.test.ts +12 -10
  97. package/test/code/ES6.src.js +136 -0
  98. package/test/code/ES6.test.ts +28 -2
  99. package/test/code/NewFeatures.test.ts +19 -0
  100. package/test/index.test.ts +15 -2
  101. package/test/probability.test.ts +44 -0
  102. package/test/templates/template.test.ts +1 -1
  103. package/test/transforms/antiTooling.test.ts +52 -0
  104. package/test/transforms/calculator.test.ts +40 -0
  105. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
  106. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  107. package/test/transforms/deadCode.test.ts +66 -15
  108. package/test/transforms/dispatcher.test.ts +44 -1
  109. package/test/transforms/es5/antiClass.test.ts +33 -0
  110. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  111. package/test/transforms/eval.test.ts +53 -0
  112. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  113. package/test/transforms/flatten.test.ts +195 -3
  114. package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
  115. package/test/transforms/identifier/renameVariables.test.ts +108 -0
  116. package/test/transforms/lock/antiDebug.test.ts +2 -2
  117. package/test/transforms/minify.test.ts +151 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +56 -29
  120. package/test/transforms/stack.test.ts +91 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +115 -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/compare.test.ts +23 -1
  127. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  128. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  129. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  130. package/src/transforms/hexadecimalNumbers.ts +0 -31
  131. package/src/transforms/hideInitializingCode.ts +0 -432
  132. package/src/transforms/label.ts +0 -64
  133. package/src/transforms/preparation/nameConflicts.ts +0 -102
  134. package/src/transforms/preparation/preparation.ts +0 -176
  135. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  136. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  137. package/test/transforms/hideInitializingCode.test.ts +0 -336
  138. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  139. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -2,6 +2,9 @@ import { isBlock } from "../../traverse";
2
2
  import { Identifier, SequenceExpression } from "../../util/gen";
3
3
  import Transform from "../transform";
4
4
 
5
+ /**
6
+ * Expression Obfuscation runs before Control Flow Flattening
7
+ */
5
8
  export default class ExpressionObfuscation extends Transform {
6
9
  constructor(o) {
7
10
  super(o);
@@ -17,10 +20,16 @@ export default class ExpressionObfuscation extends Transform {
17
20
  var deleteExprs = [];
18
21
 
19
22
  object.body.forEach((stmt, i) => {
20
- if (stmt.type == "ExpressionStatement") {
23
+ if (stmt.type == "ExpressionStatement" && !stmt.directive) {
21
24
  var expr = stmt.expression;
22
25
 
23
- if (expr.type == "UnaryExpression" && exprs.length) {
26
+ if (
27
+ expr.type == "UnaryExpression" &&
28
+ !(
29
+ expr.operator === "typeof" && expr.argument.type === "Identifier"
30
+ ) &&
31
+ exprs.length // typeof is special
32
+ ) {
24
33
  expr.argument = SequenceExpression([
25
34
  ...exprs,
26
35
  { ...expr.argument },
@@ -38,7 +47,13 @@ export default class ExpressionObfuscation extends Transform {
38
47
  stmt.test.type == "BinaryExpression" &&
39
48
  stmt.test.operator !== "**"
40
49
  ) {
41
- if (stmt.test.left.type == "UnaryExpression") {
50
+ if (
51
+ stmt.test.left.type == "UnaryExpression" &&
52
+ !(
53
+ stmt.test.left.operator === "typeof" &&
54
+ stmt.test.left.argument.type === "Identifier"
55
+ ) // typeof is special
56
+ ) {
42
57
  stmt.test.left.argument = SequenceExpression([
43
58
  ...exprs,
44
59
  { ...stmt.test.left.argument },
@@ -226,6 +226,356 @@ function setCookie(cname, cvalue, exdays) {
226
226
  getHeightBalanced,
227
227
  };
228
228
  `),
229
+ Template(`
230
+ function ListNode(){}
231
+ var addTwoNumbers = function(l1, l2) {
232
+ var carry = 0;
233
+ var sum = 0;
234
+ var head = new ListNode(0);
235
+ var now = head;
236
+ var a = l1;
237
+ var b = l2;
238
+ while (a !== null || b !== null) {
239
+ sum = (a ? a.val : 0) + (b ? b.val : 0) + carry;
240
+ carry = Math.floor(sum / 10);
241
+ now.next = new ListNode(sum % 10);
242
+ now = now.next;
243
+ a = a ? a.next : null;
244
+ b = b ? b.next : null;
245
+ }
246
+ if (carry) now.next = new ListNode(carry);
247
+ return head.next;
248
+ };
249
+
250
+ console.log(addTwoNumbers)
251
+ `),
252
+ Template(`
253
+ var threeSum = function(nums) {
254
+ var len = nums.length;
255
+ var res = [];
256
+ var l = 0;
257
+ var r = 0;
258
+ nums.sort((a, b) => (a - b));
259
+ for (var i = 0; i < len; i++) {
260
+ if (i > 0 && nums[i] === nums[i - 1]) continue;
261
+ l = i + 1;
262
+ r = len - 1;
263
+ while (l < r) {
264
+ if (nums[i] + nums[l] + nums[r] < 0) {
265
+ l++;
266
+ } else if (nums[i] + nums[l] + nums[r] > 0) {
267
+ r--;
268
+ } else {
269
+ res.push([nums[i], nums[l], nums[r]]);
270
+ while (l < r && nums[l] === nums[l + 1]) l++;
271
+ while (l < r && nums[r] === nums[r - 1]) r--;
272
+ l++;
273
+ r--;
274
+ }
275
+ }
276
+ }
277
+ return res;
278
+ };
279
+ console.log(threeSum)
280
+ `),
281
+ Template(`
282
+ var combinationSum2 = function(candidates, target) {
283
+ var res = [];
284
+ var len = candidates.length;
285
+ candidates.sort((a, b) => (a - b));
286
+ dfs(res, [], 0, len, candidates, target);
287
+ return res;
288
+ };
289
+
290
+ var dfs = function (res, stack, index, len, candidates, target) {
291
+ var tmp = null;
292
+ if (target < 0) return;
293
+ if (target === 0) return res.push(stack);
294
+ for (var i = index; i < len; i++) {
295
+ if (candidates[i] > target) break;
296
+ if (i > index && candidates[i] === candidates[i - 1]) continue;
297
+ tmp = Array.from(stack);
298
+ tmp.push(candidates[i]);
299
+ dfs(res, tmp, i + 1, len, candidates, target - candidates[i]);
300
+ }
301
+ };
302
+
303
+ console.log(combinationSum2);
304
+ `),
305
+ Template(`
306
+ var isScramble = function(s1, s2) {
307
+ return helper({}, s1, s2);
308
+ };
309
+
310
+ var helper = function (dp, s1, s2) {
311
+ var map = {};
312
+
313
+ if (dp[s1 + s2] !== undefined) return dp[s1 + s2];
314
+ if (s1 === s2) return true;
315
+
316
+ for (var j = 0; j < s1.length; j++) {
317
+ if (map[s1[j]] === undefined) map[s1[j]] = 0;
318
+ if (map[s2[j]] === undefined) map[s2[j]] = 0;
319
+ map[s1[j]]++;
320
+ map[s2[j]]--;
321
+ }
322
+
323
+ for (var key in map) {
324
+ if (map[key] !== 0) {
325
+ dp[s1 + s2] = false;
326
+ return false;
327
+ }
328
+ }
329
+
330
+ for (var i = 1; i < s1.length; i++) {
331
+ if ((helper(dp, s1.substr(0, i), s2.substr(0, i))
332
+ && helper(dp, s1.substr(i), s2.substr(i))) ||
333
+ (helper(dp, s1.substr(0, i), s2.substr(s2.length - i))
334
+ && helper(dp, s1.substr(i), s2.substr(0, s2.length - i)))) {
335
+ dp[s1 + s2] = true;
336
+ return true;
337
+ }
338
+ }
339
+
340
+ dp[s1 + s2] = false;
341
+ return false;
342
+ };
343
+
344
+ console.log(isScramble);
345
+ `),
346
+ Template(`
347
+ var candy = function(ratings) {
348
+ var len = ratings.length;
349
+ var res = [];
350
+ var sum = 0;
351
+ for (var i = 0; i < len; i++) {
352
+ res.push((i !== 0 && ratings[i] > ratings[i - 1]) ? (res[i - 1] + 1) : 1);
353
+ }
354
+ for (var j = len - 1; j >= 0; j--) {
355
+ if (j !== len - 1 && ratings[j] > ratings[j + 1]) res[j] = Math.max(res[j], res[j + 1] + 1);
356
+ sum += res[j];
357
+ }
358
+ return sum;
359
+ };
360
+
361
+ console.log(candy)
362
+ `),
363
+ Template(`
364
+ var maxPoints = function(points) {
365
+ var max = 0;
366
+ var map = {};
367
+ var localMax = 0;
368
+ var samePoint = 0;
369
+ var k = 0;
370
+ var len = points.length;
371
+ for (var i = 0; i < len; i++) {
372
+ map = {};
373
+ localMax = 0;
374
+ samePoint = 1;
375
+ for (var j = i + 1; j < len; j++) {
376
+ if (points[i].x === points[j].x && points[i].y === points[j].y) {
377
+ samePoint++;
378
+ continue;
379
+ }
380
+ if (points[i].y === points[j].y) k = Number.MAX_SAFE_INTEGER;
381
+ else k = (points[i].x - points[j].x) / (points[i].y - points[j].y);
382
+ if (!map[k]) map[k] = 0;
383
+ map[k]++;
384
+ localMax = Math.max(localMax, map[k]);
385
+ }
386
+ localMax += samePoint;
387
+ max = Math.max(max, localMax);
388
+ }
389
+ return max;
390
+ };
391
+
392
+ console.log(maxPoints)
393
+ `),
394
+ Template(`
395
+ var maximumGap = function(nums) {
396
+ var len = nums.length;
397
+ if (len < 2) return 0;
398
+
399
+ var max = Math.max(...nums);
400
+ var min = Math.min(...nums);
401
+ if (max === min) return 0;
402
+
403
+ var minBuckets = Array(len - 1).fill(Number.MAX_SAFE_INTEGER);
404
+ var maxBuckets = Array(len - 1).fill(Number.MIN_SAFE_INTEGER);
405
+ var gap = Math.ceil((max - min) / (len - 1));
406
+ var index = 0;
407
+ for (var i = 0; i < len; i++) {
408
+ if (nums[i] === min || nums[i] === max) continue;
409
+ index = Math.floor((nums[i] - min) / gap);
410
+ minBuckets[index] = Math.min(minBuckets[index], nums[i]);
411
+ maxBuckets[index] = Math.max(maxBuckets[index], nums[i]);
412
+ }
413
+
414
+ var maxGap = Number.MIN_SAFE_INTEGER;
415
+ var preVal = min;
416
+ for (var j = 0; j < len - 1; j++) {
417
+ if (minBuckets[j] === Number.MAX_SAFE_INTEGER && maxBuckets[j] === Number.MIN_SAFE_INTEGER) continue;
418
+ maxGap = Math.max(maxGap, minBuckets[j] - preVal);
419
+ preVal = maxBuckets[j];
420
+ }
421
+ maxGap = Math.max(maxGap, max - preVal);
422
+
423
+ return maxGap;
424
+ };
425
+
426
+ console.log(maximumGap);
427
+ `),
428
+ Template(`
429
+ /**
430
+ * @param {number} capacity
431
+ */
432
+ var LRUCache = function(capacity) {
433
+ this.capacity = capacity;
434
+ this.length = 0;
435
+ this.map = {};
436
+ this.head = null;
437
+ this.tail = null;
438
+ };
439
+
440
+ /**
441
+ * @param {number} key
442
+ * @return {number}
443
+ */
444
+ LRUCache.prototype.get = function(key) {
445
+ var node = this.map[key];
446
+ if (node) {
447
+ this.remove(node);
448
+ this.insert(node.key, node.val);
449
+ return node.val;
450
+ } else {
451
+ return -1;
452
+ }
453
+ };
454
+
455
+ /**
456
+ * @param {number} key
457
+ * @param {number} value
458
+ * @return {void}
459
+ */
460
+ LRUCache.prototype.put = function(key, value) {
461
+ if (this.map[key]) {
462
+ this.remove(this.map[key]);
463
+ this.insert(key, value);
464
+ } else {
465
+ if (this.length === this.capacity) {
466
+ this.remove(this.head);
467
+ this.insert(key, value);
468
+ } else {
469
+ this.insert(key, value);
470
+ this.length++;
471
+ }
472
+ }
473
+ };
474
+
475
+ /**
476
+ * Your LRUCache object will be instantiated and called as such:
477
+ * var obj = Object.create(LRUCache).createNew(capacity)
478
+ * var param_1 = obj.get(key)
479
+ * obj.put(key,value)
480
+ */
481
+
482
+ LRUCache.prototype.remove = function (node) {
483
+ var prev = node.prev;
484
+ var next = node.next;
485
+ if (next) next.prev = prev;
486
+ if (prev) prev.next = next;
487
+ if (this.head === node) this.head = next;
488
+ if (this.tail === node) this.tail = prev;
489
+ delete this.map[node.key];
490
+ };
491
+
492
+ LRUCache.prototype.insert = function (key, val) {
493
+ var node = new List(key, val);
494
+ if (!this.tail) {
495
+ this.tail = node;
496
+ this.head = node;
497
+ } else {
498
+ this.tail.next = node;
499
+ node.prev = this.tail;
500
+ this.tail = node;
501
+ }
502
+ this.map[key] = node;
503
+ };
504
+
505
+ console.log(LRUCache);
506
+ `),
507
+ Template(`
508
+ var isInterleave = function(s1, s2, s3) {
509
+ var dp = {};
510
+ if (s3.length !== s1.length + s2.length) return false;
511
+ return helper(s1, s2, s3, 0, 0, 0, dp);
512
+ };
513
+
514
+ var helper = function (s1, s2, s3, i, j, k, dp) {
515
+ var res = false;
516
+
517
+ if (k >= s3.length) return true;
518
+ if (dp['' + i + j + k] !== undefined) return dp['' + i + j + k];
519
+
520
+ if (s3[k] === s1[i] && s3[k] === s2[j]) {
521
+ res = helper(s1, s2, s3, i + 1, j, k + 1, dp) || helper(s1, s2, s3, i, j + 1, k + 1, dp);
522
+ } else if (s3[k] === s1[i]) {
523
+ res = helper(s1, s2, s3, i + 1, j, k + 1, dp);
524
+ } else if (s3[k] === s2[j]) {
525
+ res = helper(s1, s2, s3, i, j + 1, k + 1, dp);
526
+ }
527
+
528
+ dp['' + i + j + k] = res;
529
+
530
+ return res;
531
+ };
532
+
533
+ console.log(isInterleave);
534
+ `),
535
+ Template(`
536
+ var solveNQueens = function(n) {
537
+ var res = [];
538
+ if (n === 1 || n >= 4) dfs(res, [], n, 0);
539
+ return res;
540
+ };
541
+
542
+ var dfs = function (res, points, n, index) {
543
+ for (var i = index; i < n; i++) {
544
+ if (points.length !== i) return;
545
+ for (var j = 0; j < n; j++) {
546
+ if (isValid(points, [i, j])) {
547
+ points.push([i, j]);
548
+ dfs(res, points, n, i + 1);
549
+ if (points.length === n) res.push(buildRes(points));
550
+ points.pop();
551
+ }
552
+ }
553
+ }
554
+ };
555
+
556
+ var buildRes = function (points) {
557
+ var res = [];
558
+ var n = points.length;
559
+ for (var i = 0; i < n; i++) {
560
+ res[i] = '';
561
+ for (var j = 0; j < n; j++) {
562
+ res[i] += (points[i][1] === j ? 'Q' : '.');
563
+ }
564
+ }
565
+ return res;
566
+ };
567
+
568
+ var isValid = function (oldPoints, newPoint) {
569
+ var len = oldPoints.length;
570
+ for (var i = 0; i < len; i++) {
571
+ if (oldPoints[i][0] === newPoint[0] || oldPoints[i][1] === newPoint[1]) return false;
572
+ if (Math.abs((oldPoints[i][0] - newPoint[0]) / (oldPoints[i][1] - newPoint[1])) === 1) return false;
573
+ }
574
+ return true;
575
+ };
576
+
577
+ console.log(solveNQueens);
578
+ `),
229
579
  ];
230
580
 
231
581
  /**
@@ -235,7 +585,6 @@ function setCookie(cname, cvalue, exdays) {
235
585
  * - Adds fake code from various samples.
236
586
  */
237
587
  export default class DeadCode extends Transform {
238
- usedNames: Set<string>;
239
588
  made: number;
240
589
 
241
590
  constructor(o) {
@@ -253,35 +602,43 @@ export default class DeadCode extends Transform {
253
602
  }
254
603
 
255
604
  transform(object: Node, parents: Node[]) {
256
- if (ComputeProbabilityMap(this.options.deadCode)) {
257
- return () => {
258
- this.made++;
259
- if (this.made > 100) {
260
- return;
261
- }
605
+ if (!ComputeProbabilityMap(this.options.deadCode)) {
606
+ return;
607
+ }
262
608
 
263
- var name = this.getPlaceholder();
264
- var variableDeclaration = VariableDeclaration(
265
- VariableDeclarator(name, Literal(false))
266
- );
609
+ // Hard-coded limit of 100 Dead Code insertions
610
+ this.made++;
611
+ if (this.made > 100) {
612
+ return;
613
+ }
614
+
615
+ return () => {
616
+ var body = getBlockBody(object);
267
617
 
268
- var body = getBlockBody(object);
269
- var index = getRandomInteger(0, body.length);
618
+ // Do not place code before Import statements or 'use strict' directives
619
+ var safeOffset = 0;
620
+ for (var node of body) {
621
+ if (node.type === "ImportDeclaration" || node.directive) safeOffset++;
622
+ else break;
623
+ }
270
624
 
271
- var template;
272
- do {
273
- template = choice(templates);
274
- } while (this.options.es5 && template.source.includes("async"));
625
+ var index = getRandomInteger(safeOffset, body.length);
275
626
 
276
- var ifStatement = IfStatement(
277
- Identifier(name),
278
- template.compile(),
279
- null
280
- );
627
+ var name = this.getPlaceholder();
628
+ var variableDeclaration = VariableDeclaration(
629
+ VariableDeclarator(name, Literal(false))
630
+ );
281
631
 
282
- body.splice(index, 0, ifStatement);
283
- prepend(object, variableDeclaration);
284
- };
285
- }
632
+ var template;
633
+ do {
634
+ template = choice(templates);
635
+ } while (this.options.es5 && template.source.includes("async"));
636
+
637
+ var ifStatement = IfStatement(Identifier(name), template.compile(), null);
638
+
639
+ body.splice(index, 0, ifStatement);
640
+
641
+ prepend(object, variableDeclaration);
642
+ };
286
643
  }
287
644
  }
@@ -97,14 +97,15 @@ export default class Dispatcher extends Transform {
97
97
  }
98
98
 
99
99
  // Map of FunctionDeclarations
100
- var functionDeclarations: { [name: string]: Location } = {};
100
+ var functionDeclarations: { [name: string]: Location } =
101
+ Object.create(null);
101
102
 
102
103
  // Array of Identifier nodes
103
104
  var identifiers: Location[] = [];
104
105
  var illegalFnNames: Set<string> = new Set();
105
106
 
106
107
  // New Names for Functions
107
- var newFnNames: { [name: string]: string } = {}; // [old name]: randomized name
108
+ var newFnNames: { [name: string]: string } = Object.create(null); // [old name]: randomized name
108
109
 
109
110
  var context = isVarContext(object)
110
111
  ? object
@@ -123,6 +124,8 @@ export default class Dispatcher extends Transform {
123
124
 
124
125
  if (context === c) {
125
126
  if (o.type == "FunctionDeclaration" && o.id.name) {
127
+ var name = o.id.name;
128
+
126
129
  if (
127
130
  o.$requiresEval ||
128
131
  o.async ||
@@ -135,8 +138,6 @@ export default class Dispatcher extends Transform {
135
138
  illegalFnNames.add(name);
136
139
  }
137
140
 
138
- var name = o.id.name;
139
-
140
141
  // If dupe, no routing
141
142
  if (functionDeclarations[name]) {
142
143
  illegalFnNames.add(name);
@@ -202,7 +203,8 @@ export default class Dispatcher extends Transform {
202
203
 
203
204
  // Only make a dispatcher function if it caught any functions
204
205
  if (set.size > 0) {
205
- var payloadArg = `$jsc_d${this.count}_payload`;
206
+ var payloadArg =
207
+ this.getPlaceholder() + "_dispatcher_" + this.count + "_payload";
206
208
 
207
209
  var dispatcherFnName =
208
210
  this.getPlaceholder() + "_dispatcher_" + this.count;
@@ -469,7 +471,7 @@ export default class Dispatcher extends Transform {
469
471
  }
470
472
 
471
473
  var newName = newFnNames[o.name];
472
- if (!newName) {
474
+ if (!newName || typeof newName !== "string") {
473
475
  return;
474
476
  }
475
477
 
@@ -110,7 +110,16 @@ export default class AntiClass extends Transform {
110
110
  );
111
111
  }
112
112
 
113
- if (
113
+ // Support class fields
114
+ if (methodDefinition.type === "PropertyDefinition") {
115
+ var assignmentExpression = AssignmentExpression(
116
+ "=",
117
+ key,
118
+ value || Identifier("undefined")
119
+ );
120
+
121
+ pushingTo.push(ExpressionStatement(assignmentExpression));
122
+ } else if (
114
123
  methodDefinition.kind == "constructor" ||
115
124
  methodDefinition.kind == "method"
116
125
  ) {
@@ -211,6 +211,8 @@ export default class AntiDestructuring extends Transform {
211
211
  exprs.push(AssignmentExpression(operator, clone(x), realm));
212
212
 
213
213
  names.add(x.name);
214
+ } else if (x.type == "MemberExpression") {
215
+ exprs.push(AssignmentExpression(operator, clone(x), realm));
214
216
  } else if (x.type == "ObjectPattern") {
215
217
  x.properties.forEach((property) => {
216
218
  recursive(
@@ -266,7 +268,7 @@ export default class AntiDestructuring extends Transform {
266
268
  ]);
267
269
 
268
270
  if (object.type == "VariableDeclarator") {
269
- var i = getIndexDirect(object, parents);
271
+ var i = getIndexDirect(object, parents[0]);
270
272
 
271
273
  var extra = Array.from(names).map((x) => {
272
274
  return {