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
@@ -80,6 +80,10 @@ class ExpressionObfuscation extends _transform.default {
80
80
  stmt.argument = (0, _gen.SequenceExpression)([...exprs, { ...stmt.argument
81
81
  }]);
82
82
  deleteExprs.push(...exprs);
83
+ } else if (stmt.type == "ReturnStatement") {
84
+ stmt.argument = (0, _gen.SequenceExpression)([...exprs, { ...(stmt.argument || (0, _gen.Identifier)("undefined"))
85
+ }]);
86
+ deleteExprs.push(...exprs);
83
87
  }
84
88
  }
85
89
 
@@ -35,7 +35,7 @@ class SwitchCaseObfuscation extends _transform.default {
35
35
  var types = new Set();
36
36
  (0, _traverse.walk)(object.discriminant, [object, ...parents], (o, p) => {
37
37
  if (o.type) {
38
- if (o.type == "BinaryExpression" && o.operator === "+") {} else {
38
+ if (object.$controlFlowFlattening && o.type == "BinaryExpression" && o.operator === "+") {} else {
39
39
  types.add(o.type);
40
40
  }
41
41
  }
@@ -64,7 +64,7 @@ class SwitchCaseObfuscation extends _transform.default {
64
64
  return;
65
65
  }
66
66
 
67
- var factor = (0, _random.getRandomInteger)(-250, 250);
67
+ var factor = (0, _random.getRandomInteger)(-150, 150);
68
68
 
69
69
  if (factor == 0) {
70
70
  factor = 2;
@@ -25,7 +25,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
25
25
 
26
26
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
27
27
 
28
- const templates = [(0, _template.default)("\n function curCSS( elem, name, computed ) {\n var ret;\n \n computed = computed || getStyles( elem );\n \n if ( computed ) {\n ret = computed.getPropertyValue( name ) || computed[ name ];\n \n if ( ret === \"\" && !isAttached( elem ) ) {\n ret = redacted.style( elem, name );\n }\n }\n \n return ret !== undefined ?\n \n // Support: IE <=9 - 11+\n // IE returns zIndex value as an integer.\n ret + \"\" :\n ret;\n }"), (0, _template.default)("\n function Example() {\n var state = redacted.useState(false);\n return x(\n ErrorBoundary,\n null,\n x(\n DisplayName,\n null,\n )\n );\n }"), (0, _template.default)("\n const path = require('path');\nconst { version } = require('../../package');\nconst { version: dashboardPluginVersion } = require('@redacted/enterprise-plugin/package');\nconst { version: componentsVersion } = require('@redacted/components/package');\nconst { sdkVersion } = require('@redacted/enterprise-plugin');\nconst isStandaloneExecutable = require('../utils/isStandaloneExecutable');\nconst resolveLocalRedactedPath = require('./resolve-local-redacted-path');\n\nconst redactedPath = path.resolve(__dirname, '../redacted.js');"), (0, _template.default)("\nmodule.exports = async (resolveLocalRedactedPath = ()=>{throw new Error(\"No redacted path provided\")}) => {\n const cliParams = new Set(process.argv.slice(2));\n if (!cliParams.has('--version')) {\n if (cliParams.size !== 1) return false;\n if (!cliParams.has('-v')) return false;\n }\n\n const installationModePostfix = await (async (isStandaloneExecutable, redactedPath) => {\n if (isStandaloneExecutable) return ' (standalone)';\n if (redactedPath === (await resolveLocalRedactedPath())) return ' (local)';\n return '';\n })();\n\n return true;\n};"), (0, _template.default)("\nfunction setCookie(cname, cvalue, exdays) {\n var d = new Date();\n d.setTime(d.getTime() + (exdays*24*60*60*1000));\n var expires = \"expires=\"+ d.toUTCString();\n document.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n}"), (0, _template.default)("function getCookie(cname) {\n var name = cname + \"=\";\n var decodedCookie = decodeURIComponent(document.cookie);\n var ca = decodedCookie.split(';');\n for(var i = 0; i <ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) == ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) == 0) {\n return c.substring(name.length, c.length);\n }\n }\n return \"\";\n}"), (0, _template.default)("function getLocalStorageValue(key, cb){\n if ( typeof key !== \"string\" ) {\n throw new Error(\"Invalid data key provided (not type string)\")\n }\n if ( !key ) {\n throw new Error(\"Invalid data key provided (empty string)\")\n }\n var value = window.localStorage.getItem(key)\n try {\n value = JSON.parse(value)\n } catch ( e ) {\n cb(new Error(\"Serialization error for data '\" + key + \"': \" + e.message))\n }\n\n cb(null, value)\n }")];
28
+ const templates = [(0, _template.default)("\n function curCSS( elem, name, computed ) {\n var ret;\n \n computed = computed || getStyles( elem );\n \n if ( computed ) {\n ret = computed.getPropertyValue( name ) || computed[ name ];\n \n if ( ret === \"\" && !isAttached( elem ) ) {\n ret = redacted.style( elem, name );\n }\n }\n \n return ret !== undefined ?\n \n // Support: IE <=9 - 11+\n // IE returns zIndex value as an integer.\n ret + \"\" :\n ret;\n }"), (0, _template.default)("\n function Example() {\n var state = redacted.useState(false);\n return x(\n ErrorBoundary,\n null,\n x(\n DisplayName,\n null,\n )\n );\n }"), (0, _template.default)("\n const path = require('path');\nconst { version } = require('../../package');\nconst { version: dashboardPluginVersion } = require('@redacted/enterprise-plugin/package');\nconst { version: componentsVersion } = require('@redacted/components/package');\nconst { sdkVersion } = require('@redacted/enterprise-plugin');\nconst isStandaloneExecutable = require('../utils/isStandaloneExecutable');\nconst resolveLocalRedactedPath = require('./resolve-local-redacted-path');\n\nconst redactedPath = path.resolve(__dirname, '../redacted.js');"), (0, _template.default)("\nmodule.exports = async (resolveLocalRedactedPath = ()=>{throw new Error(\"No redacted path provided\")}) => {\n const cliParams = new Set(process.argv.slice(2));\n if (!cliParams.has('--version')) {\n if (cliParams.size !== 1) return false;\n if (!cliParams.has('-v')) return false;\n }\n\n const installationModePostfix = await (async (isStandaloneExecutable, redactedPath) => {\n if (isStandaloneExecutable) return ' (standalone)';\n if (redactedPath === (await resolveLocalRedactedPath())) return ' (local)';\n return '';\n })();\n\n return true;\n};"), (0, _template.default)("\nfunction setCookie(cname, cvalue, exdays) {\n var d = new Date();\n d.setTime(d.getTime() + (exdays*24*60*60*1000));\n var expires = \"expires=\"+ d.toUTCString();\n document.cookie = cname + \"=\" + cvalue + \";\" + expires + \";path=/\";\n}"), (0, _template.default)("function getCookie(cname) {\n var name = cname + \"=\";\n var decodedCookie = decodeURIComponent(document.cookie);\n var ca = decodedCookie.split(';');\n for(var i = 0; i <ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) == ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) == 0) {\n return c.substring(name.length, c.length);\n }\n }\n return \"\";\n}"), (0, _template.default)("function getLocalStorageValue(key, cb){\n if ( typeof key !== \"string\" ) {\n throw new Error(\"Invalid data key provided (not type string)\")\n }\n if ( !key ) {\n throw new Error(\"Invalid data key provided (empty string)\")\n }\n var value = window.localStorage.getItem(key)\n try {\n value = JSON.parse(value)\n } catch ( e ) {\n cb(new Error(\"Serialization error for data '\" + key + \"': \" + e.message))\n }\n\n cb(null, value)\n }"), (0, _template.default)("\n \n var __ = \"(c=ak(<~F$VU'9f)~><&85dBPL-module/from\";\n var s = \"q:function(){var ad=ad=>b(ad-29);if(!T.r[(typeof ab==ad(123)?\";\n var g = \"return U[c[c[d(-199)]-b(205)]]||V[ae(b(166))];case T.o[c[c[c[d(-199)]+d(-174)]-(c[b(119)]-(c[d(-199)]-163))]+ae(b(146))](0)==b(167)?d(-130):-d(-144)\";\n\n __.match(s + g);\n ")];
29
29
  /**
30
30
  * Adds dead code to blocks.
31
31
  *
@@ -87,17 +87,13 @@ class Dispatcher extends _transform.default {
87
87
 
88
88
  var newFnNames = {}; // [old name]: randomized name
89
89
 
90
- var context = (0, _insert.getVarContext)(object, parents);
90
+ var context = (0, _insert.isVarContext)(object) ? object : (0, _insert.getVarContext)(object, parents);
91
91
  (0, _traverse.walk)(object, parents, (o, p) => {
92
92
  if (object == o) {
93
93
  // Fix 1
94
94
  return;
95
95
  }
96
96
 
97
- if ((0, _identifiers.isWithinClass)(o, p)) {
98
- return;
99
- }
100
-
101
97
  var c = (0, _insert.getVarContext)(o, p);
102
98
 
103
99
  if (o.type == "FunctionDeclaration") {
@@ -106,7 +102,7 @@ class Dispatcher extends _transform.default {
106
102
 
107
103
  if (context === c) {
108
104
  if (o.type == "FunctionDeclaration" && o.id.name) {
109
- if (p.find(x => x.$dispatcherSkip) || o.body.type != "BlockStatement") {
105
+ if (o.$requiresEval || o.async || o.generator || p.find(x => x.$dispatcherSkip || x.type == "MethodDefinition") || o.body.type != "BlockStatement") {
110
106
  illegalFnNames.add(name);
111
107
  }
112
108
 
@@ -118,10 +114,11 @@ class Dispatcher extends _transform.default {
118
114
  }
119
115
 
120
116
  (0, _traverse.walk)(o, p, (oo, pp) => {
121
- if (oo.type == "Identifier" && oo.name == "arguments") {
122
- illegalFnNames.add(name);
123
- } else if (oo.type == "ThisExpression") {
124
- illegalFnNames.add(name);
117
+ if (oo.type == "Identifier" && oo.name == "arguments" || oo.type == "ThisExpression" || oo.type == "Super") {
118
+ if ((0, _insert.getVarContext)(oo, pp) === o) {
119
+ illegalFnNames.add(name);
120
+ return "EXIT";
121
+ }
125
122
  }
126
123
  });
127
124
  functionDeclarations[name] = [o, p];
@@ -135,6 +132,10 @@ class Dispatcher extends _transform.default {
135
132
 
136
133
  var info = (0, _identifiers.getIdentifierInfo)(o, p);
137
134
 
135
+ if (!info.spec.isReferenced) {
136
+ return;
137
+ }
138
+
138
139
  if (info.spec.isDefined) {
139
140
  if (info.isFunctionDeclaration) {
140
141
  if (p[0].id && (!functionDeclarations[p[0].id.name] || functionDeclarations[p[0].id.name][0] !== p[0])) {
@@ -145,7 +146,7 @@ class Dispatcher extends _transform.default {
145
146
  }
146
147
  } else if (info.spec.isModified) {
147
148
  illegalFnNames.add(o.name);
148
- } else if (info.spec.isReferenced) {
149
+ } else {
149
150
  identifiers.push([o, p]);
150
151
  }
151
152
  }
@@ -184,10 +185,10 @@ class Dispatcher extends _transform.default {
184
185
  type: "FunctionExpression",
185
186
  id: null
186
187
  };
188
+ this.addComment(functionExpression, name);
187
189
 
188
190
  if (def.params.length > 0) {
189
191
  const fixParam = param => {
190
- this.addComment(param, "Unloader(param): " + param.name);
191
192
  return param;
192
193
  };
193
194
 
@@ -271,7 +272,7 @@ class Dispatcher extends _transform.default {
271
272
 
272
273
  var info = (0, _identifiers.getIdentifierInfo)(o, p);
273
274
 
274
- if (info.isFunctionCall && p[0].type == "CallExpression") {
275
+ if (info.isFunctionCall && p[0].type == "CallExpression" && p[0].callee === o) {
275
276
  // Invoking call expression: `a();`
276
277
  if (o.name == dispatcherFnName) {
277
278
  return;
@@ -78,7 +78,9 @@ class DuplicateLiteralsRemoval extends _transform.default {
78
78
  super.apply(tree);
79
79
 
80
80
  if (this.arrayName && this.arrayExpression.elements.length) {
81
- (0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.arrayName, this.arrayExpression)));
81
+ var getArrayFn = this.getPlaceholder();
82
+ (0, _insert.append)(tree, (0, _gen.FunctionDeclaration)(getArrayFn, [], [(0, _gen.ReturnStatement)(this.arrayExpression)]));
83
+ (0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.arrayName, (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(getArrayFn), (0, _gen.Identifier)("call"), false), [(0, _gen.ThisExpression)()]))));
82
84
  }
83
85
  }
84
86
 
@@ -125,18 +127,11 @@ class DuplicateLiteralsRemoval extends _transform.default {
125
127
  }
126
128
 
127
129
  this.fnGetters.set(lexContext, getterName);
128
- (0, _insert.prepend)(lexContext, (0, _gen.FunctionDeclaration)(getterName, [(0, _gen.Identifier)("index")], body));
130
+ (0, _insert.prepend)(lexContext, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(getterName, (0, _gen.CallExpression)((0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.FunctionExpression)([(0, _gen.Identifier)("index")], body))]), []))));
129
131
  }
130
132
 
131
133
  var theShift = this.fnShifts.get(getterName);
132
- this.replace(object, (0, _gen.CallExpression)((0, _gen.Identifier)(getterName), [(0, _gen.Literal)(index - theShift)]));
133
- var propertyIndex = parents.findIndex(x => x.type == "Property" || x.type == "MethodDefinition");
134
-
135
- if (propertyIndex != -1) {
136
- if (!parents[propertyIndex].computed && parents[propertyIndex].key == (parents[propertyIndex - 1] || object)) {
137
- parents[propertyIndex].computed = true;
138
- }
139
- }
134
+ this.replaceIdentifierOrLiteral(object, (0, _gen.CallExpression)((0, _gen.Identifier)(getterName), [(0, _gen.Literal)(index - theShift)]), parents);
140
135
  }
141
136
 
142
137
  transform(object, parents) {
@@ -71,12 +71,16 @@ class Flatten extends _transform.default {
71
71
  }
72
72
 
73
73
  match(object, parents) {
74
- return (0, _insert.isFunction)(object) && object.body.type == "BlockStatement" && !object.generator;
74
+ return object.type == "FunctionDeclaration" && object.body.type == "BlockStatement" && !object.generator && !object.async && !object.params.find(x => x.type !== "Identifier");
75
75
  }
76
76
 
77
77
  transform(object, parents) {
78
78
  return () => {
79
79
  //
80
+ if (parents.find(x => x.type == "ClassExpression" || x.type == "ClassDeclaration" || x.type == "MethodDefinition")) {
81
+ return;
82
+ }
83
+
80
84
  var defined = new Set();
81
85
  var references = new Set();
82
86
  var modified = new Set();
@@ -129,12 +129,15 @@ class HideInitializingCode extends _transform.default {
129
129
  });
130
130
  var map = new Map();
131
131
  var fnsToMake = (0, _random.getRandomInteger)(1, 5);
132
+ var numberLiteralsMade = 1;
132
133
 
133
134
  function numberLiteral(num, depth = 1) {
134
- if (depth > 6 || Math.random() > 0.8 / depth) {
135
+ if (depth > 6 || Math.random() > 0.8 / depth || Math.random() > 80 / numberLiteralsMade) {
135
136
  return (0, _gen.Literal)(num);
136
137
  }
137
138
 
139
+ numberLiteralsMade++;
140
+
138
141
  function ternaryCall(name, param = (0, _random.getRandomInteger)(-250, 250)) {
139
142
  return (0, _gen.ConditionalExpression)((0, _gen.BinaryExpression)("==", (0, _gen.UnaryExpression)("typeof", (0, _gen.Identifier)(name)), (0, _gen.Literal)("function")), (0, _gen.CallExpression)((0, _gen.Identifier)(name), [numberLiteral(param, depth + 1)]), (0, _gen.Identifier)(name));
140
143
  }
@@ -202,7 +205,19 @@ class HideInitializingCode extends _transform.default {
202
205
  var deadNameArray = Object.keys(deadValues);
203
206
  var sampledArray = Array.from(sampledNames);
204
207
  var check = (0, _random.getRandomInteger)(-250, 250);
205
- var initName = "init" + this.getPlaceholder();
208
+ var initName = "init" + this.getPlaceholder(); // Entangle number literals
209
+
210
+ var made = 1; // Limit frequency
211
+
212
+ (0, _traverse.walk)(stmts, [], (o, p) => {
213
+ if (o.type == "Literal" && typeof o.value === "number" && Math.floor(o.value) === o.value && Math.abs(o.value) < 100000 && Math.random() < 4 / made) {
214
+ made++;
215
+ return () => {
216
+ this.replaceIdentifierOrLiteral(o, numberLiteral(o.value), p);
217
+ };
218
+ }
219
+ }); // Create the new function
220
+
206
221
  addNodes.push((0, _gen.FunctionDeclaration)(initName, [], [...stmts]));
207
222
 
208
223
  function truePredicate() {
@@ -100,11 +100,8 @@ class GlobalConcealing extends _transform.default {
100
100
 
101
101
  _defineProperty(this, "globalAnalysis", void 0);
102
102
 
103
- _defineProperty(this, "globalVar", void 0);
104
-
105
103
  this.globalAnalysis = new GlobalAnalysis(o);
106
104
  this.before.push(this.globalAnalysis);
107
- this.globalVar = null;
108
105
  }
109
106
 
110
107
  match(object, parents) {
@@ -117,6 +114,7 @@ class GlobalConcealing extends _transform.default {
117
114
  this.globalAnalysis.notGlobals.forEach(del => {
118
115
  delete globals[del];
119
116
  });
117
+ delete globals["require"];
120
118
 
121
119
  _constants.reservedIdentifiers.forEach(x => {
122
120
  delete globals[x];
@@ -132,15 +130,19 @@ class GlobalConcealing extends _transform.default {
132
130
 
133
131
  if (Object.keys(globals).length > 0) {
134
132
  var used = new Set(); // 1. Make getter function
133
+ // holds "window" or "global"
134
+
135
+ var globalVar = this.getPlaceholder(); // holds outermost "this"
135
136
 
136
- this.globalVar = this.getPlaceholder(); // "window" or "global" in node
137
+ var thisVar = this.getPlaceholder(); // "window" or "global" in node
137
138
 
138
139
  var global = this.options.globalVariables.values().next().value || "window";
139
- var callee = this.getPlaceholder(); // Returns global variable or fall backs to `this`
140
+ var getGlobalVariableFnName = this.getPlaceholder();
141
+ var getThisVariableFnName = this.getPlaceholder(); // Returns global variable or fall backs to `this`
140
142
 
141
- var functionDeclaration = (0, _template.default)("\n function ".concat(callee, "(){\n try {\n return ").concat(global, ";\n } catch (e){\n return this;\n }\n }")).single(); // 2. Replace old accessors
143
+ var getGlobalVariableFn = (0, _template.default)("\n var ".concat(getGlobalVariableFnName, " = function(){\n try {\n return ").concat(global, ";\n } catch (e){\n return ").concat(getThisVariableFnName, "[\"call\"](this);\n }\n }")).single();
144
+ var getThisVariableFn = (0, _template.default)("\n var ".concat(getThisVariableFnName, " = function(){\n try {\n return this;\n } catch (e){\n return null;\n }\n }")).single(); // 2. Replace old accessors
142
145
 
143
- var variableDeclaration = (0, _template.default)("\n var ".concat(this.globalVar, " = ").concat(callee, ".call(this);\n ")).single();
144
146
  var globalFn = this.getPlaceholder();
145
147
  var newNames = Object.create(null);
146
148
  Object.keys(globals).forEach(name => {
@@ -155,30 +157,49 @@ class GlobalConcealing extends _transform.default {
155
157
  newNames[name] = state;
156
158
  locations.forEach(([node, parents]) => {
157
159
  if (!parents.find(x => x.$dispatcherSkip)) {
160
+ // Do not replace
161
+ if (parents[0]) {
162
+ if (parents[0].type == "ClassDeclaration" || parents[0].type == "ClassExpression" || parents[0].type == "FunctionExpression" || parents[0].type == "FunctionDeclaration") {
163
+ if (parents[0].id === node) {
164
+ return;
165
+ }
166
+ }
167
+ }
168
+
158
169
  this.replace(node, (0, _gen.CallExpression)((0, _gen.Identifier)(globalFn), [(0, _gen.Literal)(state)]));
159
170
  }
160
171
  });
161
172
  }); // Adds all global variables to the switch statement
162
- // this.options.globalVariables.forEach((name) => {
163
- // if (!newNames[name]) {
164
- // var state;
165
- // do {
166
- // state = getRandomInteger(
167
- // -1000,
168
- // 1000 + used.size + this.options.globalVariables.size
169
- // );
170
- // } while (used.has(state));
171
- // used.add(state);
172
- // newNames[name] = state;
173
- // }
174
- // });
175
-
176
- (0, _insert.prepend)(object, (0, _gen.FunctionDeclaration)(globalFn, [(0, _gen.Identifier)("index")], [(0, _gen.SwitchStatement)((0, _gen.Identifier)("index"), Object.keys(newNames).map(name => {
173
+
174
+ this.options.globalVariables.forEach(name => {
175
+ if (!newNames[name]) {
176
+ var state;
177
+
178
+ do {
179
+ state = (0, _random.getRandomInteger)(-1000, 1000 + used.size + this.options.globalVariables.size * 100);
180
+ } while (used.has(state));
181
+
182
+ used.add(state);
183
+ newNames[name] = state;
184
+ }
185
+ });
186
+ var indexParamName = this.getPlaceholder();
187
+ var returnName = this.getPlaceholder();
188
+ var functionDeclaration = (0, _gen.FunctionDeclaration)(globalFn, [(0, _gen.Identifier)(indexParamName)], [(0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(returnName)), (0, _gen.SwitchStatement)((0, _gen.Identifier)(indexParamName), Object.keys(newNames).map(name => {
177
189
  var code = newNames[name];
178
- return (0, _gen.SwitchCase)((0, _gen.Literal)(code), [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(this.globalVar), (0, _gen.Literal)(name), true))]);
179
- }))]));
190
+ var body = [(0, _gen.ReturnStatement)((0, _gen.LogicalExpression)("||", (0, _gen.MemberExpression)((0, _gen.Identifier)(globalVar), (0, _gen.Literal)(name), true), (0, _gen.MemberExpression)((0, _gen.Identifier)(thisVar), (0, _gen.Literal)(name), true)))];
191
+
192
+ if (Math.random() > 0.5 && name) {
193
+ body = [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(returnName), (0, _gen.LogicalExpression)("||", (0, _gen.Literal)(name), (0, _gen.MemberExpression)((0, _gen.Identifier)(thisVar), (0, _gen.Literal)(name), true)))), (0, _gen.BreakStatement)()];
194
+ }
195
+
196
+ return (0, _gen.SwitchCase)((0, _gen.Literal)(code), body);
197
+ })), (0, _gen.ReturnStatement)((0, _gen.LogicalExpression)("||", (0, _gen.MemberExpression)((0, _gen.Identifier)(globalVar), (0, _gen.Identifier)(returnName), true), (0, _gen.MemberExpression)((0, _gen.Identifier)(thisVar), (0, _gen.Identifier)(returnName), true)))]);
198
+ var tempVar = this.getPlaceholder();
199
+ var variableDeclaration = (0, _template.default)("\n var ".concat(globalVar, ", ").concat(thisVar, ";\n ")).single();
200
+ variableDeclaration.declarations.push((0, _gen.VariableDeclarator)(tempVar, (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.FunctionExpression)([], [getGlobalVariableFn, getThisVariableFn, (0, _template.default)("return ".concat(thisVar, " = ").concat(getThisVariableFnName, "[\"call\"](this, ").concat(globalFn, "), ").concat(globalVar, " = ").concat(getGlobalVariableFnName, "[\"call\"](this)")).single()]), (0, _gen.Literal)("call"), true), [])));
180
201
  (0, _insert.prepend)(object, variableDeclaration);
181
- (0, _insert.prepend)(object, functionDeclaration);
202
+ (0, _insert.append)(object, functionDeclaration);
182
203
  }
183
204
  };
184
205
  }
@@ -19,7 +19,7 @@ var _order = require("../../order");
19
19
 
20
20
  var _identifiers = require("../../util/identifiers");
21
21
 
22
- var _compare = require("../../util/compare");
22
+ var _scope = require("../../util/scope");
23
23
 
24
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
25
 
@@ -32,99 +32,100 @@ class MovedDeclarations extends _transform.default {
32
32
  }
33
33
 
34
34
  match(object, parents) {
35
- return (0, _traverse.isBlock)(object) && (!parents[0] || !(0, _compare.isLoop)(parents[0]));
35
+ return (0, _scope.isLexicalScope)(object);
36
36
  }
37
37
 
38
38
  transform(object, parents) {
39
39
  return () => {
40
- var block = (0, _traverse.getBlock)(object, parents);
41
- var varDecs = [];
42
- var varNames = new Set();
40
+ var body = (0, _traverse.isBlock)(object) ? object.body : object.consequent;
41
+ (0, _assert.ok)(Array.isArray(body));
43
42
  var illegal = new Set();
44
- var toReplace = [];
45
- var definingIdentifiers = new Map();
43
+ var defined = new Set();
44
+ var variableDeclarations = Object.create(null);
46
45
  (0, _traverse.walk)(object, parents, (o, p) => {
47
- if (o.type == "Identifier" && !illegal.has(o.name)) {
48
- var info = (0, _identifiers.getIdentifierInfo)(o, p);
49
-
50
- if (info.spec.isDefined && definingIdentifiers.has(o.name)) {
46
+ if (o.type == "Identifier") {
47
+ if ((0, _scope.getLexicalScope)(o, p) !== object) {
51
48
  illegal.add(o.name);
52
- this.log(o.name, "is illegal due to detected being redefined");
53
- }
49
+ } else {
50
+ var info = (0, _identifiers.getIdentifierInfo)(o, p);
54
51
 
55
- if (info.spec.isDefined && p.find(x => x.type == "SwitchCase")) {
56
- illegal.add(o.name);
57
- this.log(o.name, "is illegal due being in switch case");
58
- }
52
+ if (!info.spec.isReferenced) {
53
+ return;
54
+ }
59
55
 
60
- if (o.hidden) {
61
- illegal.add(o.name);
56
+ if (info.spec.isDefined) {
57
+ if (info.isFunctionDeclaration || info.isClassDeclaration) {
58
+ illegal.add(o.name);
59
+ } else {
60
+ if (defined.has(o.name)) {
61
+ illegal.add(o.name);
62
+ } else {
63
+ defined.add(o.name);
64
+ }
65
+ }
66
+ }
62
67
  }
63
68
  }
64
69
 
65
- var s = (0, _traverse.getBlock)(o, p);
66
-
67
- if (s == block) {
70
+ if (o.type == "VariableDeclaration") {
68
71
  return () => {
69
- if (o.type == "VariableDeclaration" && o.declarations.length && o.kind !== "let" && !o.declarations.find(x => x.id.type !== "Identifier" || illegal.has(x.id.name))) {
70
- var index = block.body.indexOf(o);
71
-
72
- if (index === 0 || o.hidden) {
73
- o.declarations.forEach(x => {
74
- illegal.add(x.id.name);
75
- });
76
- this.log(o.declarations.map(x => x.id.name).join(", "), "is/are illegal due to already being at the top");
72
+ if (o.declarations.length === 1 && o.declarations[0].id.type === "Identifier") {
73
+ var name = o.declarations[0].id.name; // Check if duplicate
74
+
75
+ if (variableDeclarations[name] || o.kind !== "var") {
76
+ illegal.add(name);
77
77
  return;
78
- }
78
+ } // Check if already at top
79
79
 
80
- if ((0, _insert.isForInitialize)(o, p)) {
81
- this.log(o.declarations.map(x => x.id.name).join(", "), "is/are illegal due to being in for initializer");
80
+
81
+ if (body[0] === o) {
82
+ illegal.add(name);
82
83
  return;
83
84
  }
84
85
 
85
- var isIllegal = false;
86
- o.declarations.forEach(x => {
87
- if (varNames.has(x.id.name)) {
88
- illegal.add(x.id.name);
89
- isIllegal = true;
90
- this.log(x.id.name, "is illegal due to already being defined");
91
- }
92
- });
93
-
94
- if (!isIllegal) {
95
- varDecs.push([o, p]);
96
- o.declarations.forEach(x => {
97
- (0, _assert.ok)(x.id.name);
98
- varNames.add(x.id.name);
99
- definingIdentifiers.set(x.id.name, x.id);
100
- }); // Change this line to assignment expressions
101
-
102
- var assignmentExpressions = o.declarations.map(x => (0, _gen.AssignmentExpression)("=", (0, _insert.clone)(x.id), (0, _insert.clone)(x.init) || (0, _gen.Identifier)("undefined")));
103
- (0, _assert.ok)(assignmentExpressions.length, "Should be at least 1");
104
- var value = (0, _gen.SequenceExpression)(assignmentExpressions);
105
- value = (0, _gen.ExpressionStatement)(value);
106
- toReplace.push([o.declarations.map(x => x.id.name), o, value]);
86
+ var replace = (0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(name), o.declarations[0].init || (0, _gen.Identifier)("undefined"));
87
+ var forType = (0, _insert.isForInitialize)(o, p);
88
+
89
+ if (forType === "left-hand") {
90
+ replace = (0, _gen.Identifier)(name);
91
+ } else if (!forType) {
92
+ replace = (0, _gen.ExpressionStatement)(replace);
107
93
  }
94
+
95
+ variableDeclarations[name] = {
96
+ location: [o, p],
97
+ replace: replace
98
+ };
108
99
  }
109
100
  };
110
101
  }
111
102
  });
112
103
  illegal.forEach(name => {
113
- varNames.delete(name);
104
+ delete variableDeclarations[name];
114
105
  });
115
- toReplace.forEach(x => {
116
- if (!x[0].find(x => illegal.has(x))) {
117
- this.replace(x[1], x[2]);
118
- }
119
- }); // Define the names in this block as 1 variable declaration
120
-
121
- if (varNames.size > 0) {
122
- this.log("Moved", varNames);
123
- var variableDeclaration = (0, _gen.VariableDeclaration)(Array.from(varNames).map(x => {
124
- return (0, _gen.VariableDeclarator)(x);
125
- }));
126
- (0, _insert.prepend)(block, variableDeclaration);
106
+ var movingNames = Object.keys(variableDeclarations);
107
+
108
+ if (movingNames.length === 0) {
109
+ return;
127
110
  }
111
+
112
+ var variableDeclaration = (0, _gen.VariableDeclaration)(movingNames.map(name => {
113
+ return (0, _gen.VariableDeclarator)(name);
114
+ }));
115
+
116
+ if (object.type == "Program") {
117
+ (0, _insert.prepend)(object, variableDeclaration);
118
+ } else {
119
+ body.unshift(variableDeclaration);
120
+ }
121
+
122
+ movingNames.forEach(name => {
123
+ var {
124
+ location,
125
+ replace
126
+ } = variableDeclarations[name];
127
+ this.replace(location[0], replace);
128
+ });
128
129
  };
129
130
  }
130
131