js-confuser 1.7.1 → 1.7.2

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 (123) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +12 -27
  3. package/dist/compiler.js +2 -8
  4. package/dist/constants.js +17 -10
  5. package/dist/index.js +7 -30
  6. package/dist/obfuscator.js +15 -62
  7. package/dist/options.js +21 -38
  8. package/dist/order.js +4 -7
  9. package/dist/parser.js +5 -13
  10. package/dist/precedence.js +6 -8
  11. package/dist/presets.js +4 -6
  12. package/dist/probability.js +13 -24
  13. package/dist/templates/bufferToString.js +100 -5
  14. package/dist/templates/crash.js +51 -9
  15. package/dist/templates/es5.js +125 -6
  16. package/dist/templates/functionLength.js +24 -6
  17. package/dist/templates/globals.js +9 -0
  18. package/dist/templates/template.js +71 -30
  19. package/dist/transforms/antiTooling.js +26 -22
  20. package/dist/transforms/calculator.js +18 -54
  21. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +236 -333
  22. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
  23. package/dist/transforms/deadCode.js +528 -27
  24. package/dist/transforms/dispatcher.js +106 -110
  25. package/dist/transforms/es5/antiClass.js +70 -44
  26. package/dist/transforms/es5/antiDestructuring.js +14 -38
  27. package/dist/transforms/es5/antiES6Object.js +39 -48
  28. package/dist/transforms/es5/antiSpreadOperator.js +5 -14
  29. package/dist/transforms/es5/antiTemplate.js +10 -19
  30. package/dist/transforms/es5/es5.js +7 -40
  31. package/dist/transforms/extraction/classExtraction.js +83 -0
  32. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
  33. package/dist/transforms/extraction/objectExtraction.js +24 -56
  34. package/dist/transforms/finalizer.js +6 -20
  35. package/dist/transforms/flatten.js +51 -99
  36. package/dist/transforms/identifier/globalAnalysis.js +8 -26
  37. package/dist/transforms/identifier/globalConcealing.js +35 -54
  38. package/dist/transforms/identifier/movedDeclarations.js +66 -38
  39. package/dist/transforms/identifier/renameVariables.js +29 -68
  40. package/dist/transforms/identifier/variableAnalysis.js +21 -48
  41. package/dist/transforms/lock/antiDebug.js +20 -25
  42. package/dist/transforms/lock/integrity.js +48 -47
  43. package/dist/transforms/lock/lock.js +62 -113
  44. package/dist/transforms/minify.js +77 -108
  45. package/dist/transforms/opaquePredicates.js +11 -48
  46. package/dist/transforms/preparation.js +17 -50
  47. package/dist/transforms/renameLabels.js +5 -22
  48. package/dist/transforms/rgf.js +93 -69
  49. package/dist/transforms/shuffle.js +41 -46
  50. package/dist/transforms/stack.js +35 -98
  51. package/dist/transforms/string/encoding.js +73 -27
  52. package/dist/transforms/string/stringCompression.js +44 -68
  53. package/dist/transforms/string/stringConcealing.js +125 -134
  54. package/dist/transforms/string/stringEncoding.js +6 -26
  55. package/dist/transforms/string/stringSplitting.js +5 -30
  56. package/dist/transforms/transform.js +50 -100
  57. package/dist/traverse.js +11 -18
  58. package/dist/util/compare.js +27 -29
  59. package/dist/util/gen.js +32 -86
  60. package/dist/util/guard.js +0 -1
  61. package/dist/util/identifiers.js +9 -72
  62. package/dist/util/insert.js +27 -77
  63. package/dist/util/math.js +0 -3
  64. package/dist/util/object.js +3 -7
  65. package/dist/util/random.js +5 -36
  66. package/dist/util/scope.js +6 -3
  67. package/package.json +3 -3
  68. package/src/constants.ts +12 -0
  69. package/src/options.ts +13 -0
  70. package/src/order.ts +2 -2
  71. package/src/templates/bufferToString.ts +49 -11
  72. package/src/templates/functionLength.ts +21 -3
  73. package/src/templates/globals.ts +3 -0
  74. package/src/templates/template.ts +85 -25
  75. package/src/transforms/antiTooling.ts +33 -11
  76. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +2 -2
  77. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
  78. package/src/transforms/deadCode.ts +0 -16
  79. package/src/transforms/dispatcher.ts +91 -69
  80. package/src/transforms/es5/antiClass.ts +10 -1
  81. package/src/transforms/extraction/classExtraction.ts +168 -0
  82. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -10
  83. package/src/transforms/extraction/objectExtraction.ts +4 -15
  84. package/src/transforms/flatten.ts +20 -5
  85. package/src/transforms/identifier/globalConcealing.ts +29 -65
  86. package/src/transforms/identifier/movedDeclarations.ts +90 -24
  87. package/src/transforms/minify.ts +27 -12
  88. package/src/transforms/rgf.ts +94 -5
  89. package/src/transforms/stack.ts +12 -3
  90. package/src/transforms/string/encoding.ts +85 -51
  91. package/src/transforms/string/stringCompression.ts +5 -8
  92. package/src/transforms/string/stringConcealing.ts +139 -113
  93. package/src/transforms/string/stringEncoding.ts +1 -2
  94. package/src/transforms/string/stringSplitting.ts +1 -2
  95. package/src/transforms/transform.ts +30 -1
  96. package/src/util/compare.ts +39 -5
  97. package/src/util/gen.ts +10 -3
  98. package/src/util/insert.ts +17 -0
  99. package/src/util/scope.ts +14 -2
  100. package/test/code/Cash.test.ts +10 -4
  101. package/test/code/StrictMode.src.js +65 -0
  102. package/test/code/StrictMode.test.js +37 -0
  103. package/test/compare.test.ts +62 -2
  104. package/test/options.test.ts +111 -55
  105. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
  106. package/test/transforms/dispatcher.test.ts +55 -0
  107. package/test/transforms/extraction/classExtraction.test.ts +86 -0
  108. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
  109. package/test/transforms/extraction/objectExtraction.test.ts +2 -0
  110. package/test/transforms/identifier/globalConcealing.test.ts +19 -0
  111. package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
  112. package/test/transforms/minify.test.ts +37 -0
  113. package/test/transforms/rgf.test.ts +50 -0
  114. package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
  115. package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
  116. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
  117. package/dist/transforms/eval.js +0 -84
  118. package/dist/transforms/hexadecimalNumbers.js +0 -63
  119. package/dist/transforms/hideInitializingCode.js +0 -270
  120. package/dist/transforms/identifier/nameRecycling.js +0 -218
  121. package/dist/transforms/label.js +0 -67
  122. package/dist/transforms/preparation/nameConflicts.js +0 -116
  123. package/dist/transforms/preparation/preparation.js +0 -188
@@ -1,19 +1,59 @@
1
+ import {
2
+ placeholderVariablePrefix,
3
+ predictableFunctionTag,
4
+ } from "../constants";
1
5
  import Template from "./template";
2
6
 
3
- export const BufferToStringTemplate = Template(`
4
- function __getGlobal(){
7
+ export const GetGlobalTemplate = Template(`
8
+ function ${placeholderVariablePrefix}CFG__getGlobalThis${predictableFunctionTag}(){
9
+ return globalThis
10
+ }
11
+
12
+ function ${placeholderVariablePrefix}CFG__getGlobal${predictableFunctionTag}(){
13
+ return global
14
+ }
15
+
16
+ function ${placeholderVariablePrefix}CFG__getWindow${predictableFunctionTag}(){
17
+ return window
18
+ }
19
+
20
+ function ${placeholderVariablePrefix}CFG__getThisFunction${predictableFunctionTag}(){
21
+ return new Function("return this")()
22
+ }
23
+
24
+ function {getGlobalFnName}(array = [
25
+ ${placeholderVariablePrefix}CFG__getGlobalThis${predictableFunctionTag},
26
+ ${placeholderVariablePrefix}CFG__getGlobal${predictableFunctionTag},
27
+ ${placeholderVariablePrefix}CFG__getWindow${predictableFunctionTag},
28
+ ${placeholderVariablePrefix}CFG__getThisFunction${predictableFunctionTag}
29
+ ]){
30
+ var bestMatch
31
+ var itemsToSearch = []
5
32
  try {
6
- return global||window|| ( new Function("return this") )();
7
- } catch ( e ) {
33
+ bestMatch = Object
34
+ itemsToSearch["push"](("")["__proto__"]["constructor"]["name"])
35
+ } catch(e) {
36
+
37
+ }
38
+ A: for(var i = 0; i < array["length"]; i++) {
8
39
  try {
9
- return this;
10
- } catch ( e ) {
11
- return {};
12
- }
40
+ bestMatch = array[i]()
41
+ for(var j = 0; j < itemsToSearch["length"]; j++) {
42
+ if(typeof bestMatch[itemsToSearch[j]] === "undefined") continue A;
43
+ }
44
+ return bestMatch
45
+ } catch(e) {}
13
46
  }
47
+
48
+ return bestMatch || this;
14
49
  }
50
+ `);
15
51
 
16
- var __globalObject = __getGlobal() || {};
52
+ export const BufferToStringTemplate = Template(`
53
+
54
+ ${GetGlobalTemplate.source}
55
+
56
+ var __globalObject = {getGlobalFnName}() || {};
17
57
  var __TextDecoder = __globalObject["TextDecoder"];
18
58
  var __Uint8Array = __globalObject["Uint8Array"];
19
59
  var __Buffer = __globalObject["Buffer"];
@@ -63,6 +103,4 @@ export const BufferToStringTemplate = Template(`
63
103
  return utf8ArrayToStr(buffer);
64
104
  }
65
105
  }
66
-
67
-
68
106
  `);
@@ -3,12 +3,30 @@ import Template from "./template";
3
3
  /**
4
4
  * Helper function to set `function.length` property.
5
5
  */
6
- export const FunctionLengthTemplate = Template(`
6
+ export const FunctionLengthTemplate = Template(
7
+ `
7
8
  function {name}(functionObject, functionLength){
8
- Object["defineProperty"](functionObject, "length", {
9
+ {ObjectDefineProperty}(functionObject, "length", {
9
10
  "value": functionLength,
10
11
  "configurable": true
11
12
  });
12
13
  return functionObject;
13
14
  }
14
- `);
15
+ `,
16
+ `
17
+ function {name}(functionObject, functionLength){
18
+ return {ObjectDefineProperty}(functionObject, "length", {
19
+ "value": functionLength,
20
+ "configurable": true
21
+ });
22
+ }
23
+ `,
24
+ `
25
+ function {name}(functionObject, functionLength){
26
+ return {ObjectDefineProperty}["call"](null, functionObject, "length", {
27
+ "value": functionLength,
28
+ "configurable": true
29
+ });
30
+ }
31
+ `
32
+ );
@@ -0,0 +1,3 @@
1
+ import Template from "./template";
2
+
3
+ export const ObjectDefineProperty = Template(`Object["defineProperty"]`);
@@ -1,57 +1,103 @@
1
1
  import { Node } from "../util/gen";
2
2
  import { parseSnippet, parseSync } from "../parser";
3
+ import { ok } from "assert";
4
+ import { choice } from "../util/random";
5
+ import { placeholderVariablePrefix } from "../constants";
3
6
 
4
7
  export interface ITemplate {
5
- fill(variables?: { [name: string]: string | number }): string;
8
+ fill(variables?: { [name: string]: string | number }): {
9
+ output: string;
10
+ template: string;
11
+ };
6
12
 
7
13
  compile(variables?: { [name: string]: string | number }): Node[];
8
14
 
9
15
  single(variables?: { [name: string]: string | number }): Node;
10
16
 
17
+ variables(variables): ITemplate;
18
+
19
+ ignoreMissingVariables(): ITemplate;
20
+
21
+ templates: string[];
11
22
  source: string;
12
23
  }
13
24
 
14
- export default function Template(template: string): ITemplate {
15
- var neededVariables = 0;
16
- while (template.includes(`{$${neededVariables + 1}}`)) {
17
- neededVariables++;
25
+ export default function Template(...templates: string[]): ITemplate {
26
+ ok(templates.length);
27
+
28
+ var requiredVariables = new Set<string>();
29
+ var providedVariables = {};
30
+ var defaultVariables: { [key: string]: string } = Object.create(null);
31
+
32
+ // This may picked up "$mb[pP`x]" from String Encoding function
33
+ // ignoreMissingVariables() prevents this
34
+ var matches = templates[0].match(/{[$A-z0-9_]+}/g);
35
+ if (matches !== null) {
36
+ matches.forEach((variable) => {
37
+ var name = variable.slice(1, -1);
38
+
39
+ // $ variables are for default variables
40
+ if (name.startsWith("$")) {
41
+ defaultVariables[name] =
42
+ placeholderVariablePrefix +
43
+ "td_" +
44
+ Object.keys(defaultVariables).length;
45
+ } else {
46
+ requiredVariables.add(name);
47
+ }
48
+ });
18
49
  }
19
- var vars = Object.create(null);
20
- new Array(neededVariables + 1).fill(0).forEach((x, i) => {
21
- vars["\\$" + i] = "temp_" + i;
22
- });
23
-
24
- function fill(variables?: { [name: string]: string | number }): string {
25
- if (!variables) {
26
- variables = Object.create(null);
27
- }
28
50
 
29
- var cloned = template;
51
+ function fill(
52
+ variables: { [name: string]: string | number } = Object.create(null)
53
+ ) {
54
+ var userVariables = { ...providedVariables, ...variables };
55
+
56
+ // Validate all variables were passed in
57
+ for (var requiredVariable of requiredVariables) {
58
+ if (typeof userVariables[requiredVariable] === "undefined") {
59
+ throw new Error(
60
+ templates[0] +
61
+ " missing variable: " +
62
+ requiredVariable +
63
+ " from " +
64
+ JSON.stringify(userVariables)
65
+ );
66
+ }
67
+ }
30
68
 
31
- var keys = { ...variables, ...vars };
69
+ var template = choice(templates);
70
+ var output = template;
71
+ var allVariables = {
72
+ ...defaultVariables,
73
+ ...userVariables,
74
+ };
32
75
 
33
- Object.keys(keys).forEach((name) => {
34
- var bracketName = "{" + name + "}";
35
- var value = keys[name] + "";
76
+ Object.keys(allVariables).forEach((name) => {
77
+ var bracketName = "{" + name.replace("$", "\\$") + "}";
78
+ var value = allVariables[name] + "";
36
79
 
37
80
  var reg = new RegExp(bracketName, "g");
38
81
 
39
- cloned = cloned.replace(reg, value);
82
+ output = output.replace(reg, value);
40
83
  });
41
84
 
42
- return cloned;
85
+ return { output, template };
43
86
  }
44
87
 
45
88
  function compile(variables: { [name: string]: string | number }): Node[] {
46
- var code = fill(variables);
89
+ var { output, template } = fill(variables);
47
90
  try {
48
- var program = parseSnippet(code);
91
+ var program = parseSnippet(output);
49
92
 
50
93
  return program.body;
51
94
  } catch (e) {
52
95
  console.error(e);
53
96
  console.error(template);
54
- throw new Error("Template failed to parse");
97
+ console.error({ ...providedVariables, ...variables });
98
+ throw new Error(
99
+ "Template failed to parse: OUTPUT= " + output + " SOURCE= " + template
100
+ );
55
101
  }
56
102
  }
57
103
 
@@ -60,11 +106,25 @@ export default function Template(template: string): ITemplate {
60
106
  return nodes[0];
61
107
  }
62
108
 
109
+ function variables(newVariables) {
110
+ Object.assign(providedVariables, newVariables);
111
+ return obj;
112
+ }
113
+
114
+ function ignoreMissingVariables() {
115
+ defaultVariables = Object.create(null);
116
+ requiredVariables.clear();
117
+ return obj;
118
+ }
119
+
63
120
  var obj: ITemplate = {
64
121
  fill,
65
122
  compile,
66
123
  single,
67
- source: template,
124
+ templates,
125
+ variables,
126
+ ignoreMissingVariables,
127
+ source: templates[0],
68
128
  };
69
129
 
70
130
  return obj;
@@ -1,32 +1,51 @@
1
1
  import { ObfuscateOrder } from "../order";
2
+ import Template from "../templates/template";
2
3
  import { isBlock } from "../traverse";
3
4
  import {
5
+ Node,
4
6
  ExpressionStatement,
5
- SequenceExpression,
6
- UnaryExpression,
7
+ CallExpression,
8
+ Identifier,
7
9
  } from "../util/gen";
8
- import { choice } from "../util/random";
10
+ import { prepend } from "../util/insert";
9
11
  import Transform from "./transform";
10
12
 
11
13
  // JsNice.org tries to separate sequence expressions into multiple lines, this stops that.
12
14
  export default class AntiTooling extends Transform {
15
+ fnName: string;
16
+
13
17
  constructor(o) {
14
18
  super(o, ObfuscateOrder.AntiTooling);
15
19
  }
16
20
 
21
+ apply(tree: Node) {
22
+ super.apply(tree);
23
+
24
+ if (typeof this.fnName === "string") {
25
+ prepend(
26
+ tree,
27
+ Template(`
28
+ function {fnName}(){
29
+ }
30
+ `).single({ fnName: this.fnName })
31
+ );
32
+ }
33
+ }
34
+
17
35
  match(object, parents) {
18
36
  return isBlock(object) || object.type == "SwitchCase";
19
37
  }
20
38
 
21
39
  transform(object, parents) {
22
40
  return () => {
23
- var exprs = [];
24
- var deleteExprs = [];
41
+ var exprs: Node[] = [];
42
+ var deleteExprs: Node[] = [];
25
43
 
26
- var body = object.type == "SwitchCase" ? object.consequent : object.body;
44
+ var body: Node[] =
45
+ object.type == "SwitchCase" ? object.consequent : object.body;
27
46
 
28
47
  const end = () => {
29
- function flatten(expr) {
48
+ function flatten(expr: Node) {
30
49
  if (expr.type == "ExpressionStatement") {
31
50
  flatten(expr.expression);
32
51
  } else if (expr.type == "SequenceExpression") {
@@ -41,13 +60,16 @@ export default class AntiTooling extends Transform {
41
60
 
42
61
  if (flattened.length > 1) {
43
62
  flattened[0] = { ...flattened[0] };
63
+
64
+ if (!this.fnName) {
65
+ this.fnName = this.getPlaceholder();
66
+ }
67
+
68
+ // (expr1,expr2,expr3) -> F(expr1, expr2, expr3)
44
69
  this.replace(
45
70
  exprs[0],
46
71
  ExpressionStatement(
47
- UnaryExpression(
48
- choice(["typeof", "void", "!"]),
49
- SequenceExpression(flattened)
50
- )
72
+ CallExpression(Identifier(this.fnName), [...flattened])
51
73
  )
52
74
  );
53
75
 
@@ -47,9 +47,8 @@ import {
47
47
  import { chance, choice, getRandomInteger, shuffle } from "../../util/random";
48
48
  import Transform from "../transform";
49
49
  import ExpressionObfuscation from "./expressionObfuscation";
50
- import { isModuleSource } from "../string/stringConcealing";
51
50
  import { reservedIdentifiers } from "../../constants";
52
- import { isDirective } from "../../util/compare";
51
+ import { isDirective, isModuleSource } from "../../util/compare";
53
52
 
54
53
  const flattenStructures = new Set([
55
54
  "IfStatement",
@@ -1571,6 +1570,7 @@ export default class ControlFlowFlattening extends Transform {
1571
1570
  !this.isDebug &&
1572
1571
  o.type === "Identifier" &&
1573
1572
  this.mangleIdentifiers &&
1573
+ !reservedIdentifiers.has(o.name) &&
1574
1574
  chance(50 - this.mangledExpressionsMade / 100) &&
1575
1575
  !p.find((x) => isVarContext(x))
1576
1576
  ) {
@@ -1,15 +1,48 @@
1
+ import { criticalFunctionTag } from "../../constants";
2
+ import Template from "../../templates/template";
1
3
  import { isBlock } from "../../traverse";
2
- import { Identifier, SequenceExpression } from "../../util/gen";
4
+ import {
5
+ CallExpression,
6
+ Identifier,
7
+ Node,
8
+ SequenceExpression,
9
+ } from "../../util/gen";
10
+ import { prepend } from "../../util/insert";
3
11
  import Transform from "../transform";
4
12
 
5
13
  /**
6
14
  * Expression Obfuscation runs before Control Flow Flattening
7
15
  */
8
16
  export default class ExpressionObfuscation extends Transform {
17
+ fnName: string;
18
+
9
19
  constructor(o) {
10
20
  super(o);
11
21
  }
12
22
 
23
+ apply(tree: Node): void {
24
+ super.apply(tree);
25
+
26
+ if (typeof this.fnName === "string") {
27
+ prepend(
28
+ tree,
29
+ Template(`
30
+ function {fnName}(...args){
31
+ return args[args["length"] - 1]
32
+ }
33
+ `).single({ fnName: this.fnName })
34
+ );
35
+ }
36
+ }
37
+
38
+ createSequenceExpression(expressions: Node[]): Node {
39
+ if (!this.fnName) {
40
+ this.fnName = this.getPlaceholder() + criticalFunctionTag;
41
+ }
42
+
43
+ return CallExpression(Identifier(this.fnName), [...expressions]);
44
+ }
45
+
13
46
  match(object, parents) {
14
47
  return isBlock(object);
15
48
  }
@@ -54,12 +87,12 @@ export default class ExpressionObfuscation extends Transform {
54
87
  stmt.test.left.argument.type === "Identifier"
55
88
  ) // typeof is special
56
89
  ) {
57
- stmt.test.left.argument = SequenceExpression([
90
+ stmt.test.left.argument = this.createSequenceExpression([
58
91
  ...exprs,
59
92
  { ...stmt.test.left.argument },
60
93
  ]);
61
94
  } else {
62
- stmt.test.left = SequenceExpression([
95
+ stmt.test.left = this.createSequenceExpression([
63
96
  ...exprs,
64
97
  { ...stmt.test.left },
65
98
  ]);
@@ -70,12 +103,15 @@ export default class ExpressionObfuscation extends Transform {
70
103
  stmt.test.operator !== "**" &&
71
104
  stmt.test.left.left.type == "UnaryExpression"
72
105
  ) {
73
- stmt.test.left.left.argument = SequenceExpression([
106
+ stmt.test.left.left.argument = this.createSequenceExpression([
74
107
  ...exprs,
75
108
  { ...stmt.test.left.left.argument },
76
109
  ]);
77
110
  } else {
78
- stmt.test = SequenceExpression([...exprs, { ...stmt.test }]);
111
+ stmt.test = this.createSequenceExpression([
112
+ ...exprs,
113
+ { ...stmt.test },
114
+ ]);
79
115
  }
80
116
  deleteExprs.push(...exprs);
81
117
  } else if (
@@ -88,7 +124,7 @@ export default class ExpressionObfuscation extends Transform {
88
124
 
89
125
  if (init) {
90
126
  if (init.type == "VariableDeclaration") {
91
- init.declarations[0].init = SequenceExpression([
127
+ init.declarations[0].init = this.createSequenceExpression([
92
128
  ...exprs,
93
129
  {
94
130
  ...(init.declarations[0].init || Identifier("undefined")),
@@ -96,7 +132,7 @@ export default class ExpressionObfuscation extends Transform {
96
132
  ]);
97
133
  deleteExprs.push(...exprs);
98
134
  } else if (init.type == "AssignmentExpression") {
99
- init.right = SequenceExpression([
135
+ init.right = this.createSequenceExpression([
100
136
  ...exprs,
101
137
  {
102
138
  ...(init.right || Identifier("undefined")),
@@ -106,7 +142,7 @@ export default class ExpressionObfuscation extends Transform {
106
142
  }
107
143
  }
108
144
  } else if (stmt.type == "VariableDeclaration") {
109
- stmt.declarations[0].init = SequenceExpression([
145
+ stmt.declarations[0].init = this.createSequenceExpression([
110
146
  ...exprs,
111
147
  {
112
148
  ...(stmt.declarations[0].init || Identifier("undefined")),
@@ -114,13 +150,13 @@ export default class ExpressionObfuscation extends Transform {
114
150
  ]);
115
151
  deleteExprs.push(...exprs);
116
152
  } else if (stmt.type == "ThrowStatement") {
117
- stmt.argument = SequenceExpression([
153
+ stmt.argument = this.createSequenceExpression([
118
154
  ...exprs,
119
155
  { ...stmt.argument },
120
156
  ]);
121
157
  deleteExprs.push(...exprs);
122
158
  } else if (stmt.type == "ReturnStatement") {
123
- stmt.argument = SequenceExpression([
159
+ stmt.argument = this.createSequenceExpression([
124
160
  ...exprs,
125
161
  { ...(stmt.argument || Identifier("undefined")) },
126
162
  ]);
@@ -188,10 +188,6 @@ function setCookie(cname, cvalue, exdays) {
188
188
  return true;
189
189
  }
190
190
 
191
- /**
192
- * @param {TreeNode} root
193
- * @return {boolean}
194
- */
195
191
  function isBalanced(root) {
196
192
  const height = getHeightBalanced(root);
197
193
  return height !== Infinity;
@@ -426,9 +422,6 @@ function setCookie(cname, cvalue, exdays) {
426
422
  console.log(maximumGap);
427
423
  `),
428
424
  Template(`
429
- /**
430
- * @param {number} capacity
431
- */
432
425
  var LRUCache = function(capacity) {
433
426
  this.capacity = capacity;
434
427
  this.length = 0;
@@ -437,10 +430,6 @@ function setCookie(cname, cvalue, exdays) {
437
430
  this.tail = null;
438
431
  };
439
432
 
440
- /**
441
- * @param {number} key
442
- * @return {number}
443
- */
444
433
  LRUCache.prototype.get = function(key) {
445
434
  var node = this.map[key];
446
435
  if (node) {
@@ -452,11 +441,6 @@ function setCookie(cname, cvalue, exdays) {
452
441
  }
453
442
  };
454
443
 
455
- /**
456
- * @param {number} key
457
- * @param {number} value
458
- * @return {void}
459
- */
460
444
  LRUCache.prototype.put = function(key, value) {
461
445
  if (this.map[key]) {
462
446
  this.remove(this.map[key]);