js-confuser 1.5.9 → 1.7.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.
- package/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +55 -0
- package/README.md +346 -165
- package/dist/constants.js +6 -2
- package/dist/index.js +9 -21
- package/dist/obfuscator.js +19 -31
- package/dist/options.js +5 -5
- package/dist/order.js +1 -3
- package/dist/presets.js +6 -7
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +3 -3
- package/dist/templates/es5.js +18 -0
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +8 -4
- package/dist/transforms/es5/antiDestructuring.js +2 -0
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +229 -148
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +35 -88
- package/dist/transforms/identifier/renameVariables.js +124 -59
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +60 -57
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +139 -247
- package/dist/transforms/stack.js +128 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +12 -19
- package/dist/traverse.js +24 -10
- package/dist/util/gen.js +17 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +35 -4
- package/dist/util/random.js +15 -0
- package/docs/ControlFlowFlattening.md +595 -0
- package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
- package/{Integrity.md → docs/Integrity.md} +2 -2
- package/docs/RGF.md +419 -0
- package/package.json +5 -5
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -2
- package/src/obfuscator.ts +19 -31
- package/src/options.ts +14 -103
- package/src/order.ts +1 -5
- package/src/presets.ts +6 -7
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +15 -19
- package/src/templates/es5.ts +131 -0
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +9 -4
- package/src/transforms/es5/antiDestructuring.ts +2 -0
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
- package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
- package/src/transforms/flatten.ts +357 -300
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +49 -102
- package/src/transforms/identifier/renameVariables.ts +149 -78
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +91 -75
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +213 -405
- package/src/transforms/stack.ts +156 -36
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +39 -9
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +21 -23
- package/src/traverse.ts +23 -4
- package/src/types.ts +2 -1
- package/src/util/gen.ts +28 -3
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +38 -3
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +146 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/index.test.ts +2 -1
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +22 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +20 -1
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/flatten.test.ts +399 -86
- package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
- package/test/transforms/identifier/renameVariables.test.ts +119 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +104 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +261 -381
- package/test/transforms/stack.test.ts +143 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +82 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
|
@@ -23,6 +23,8 @@ var _transform = _interopRequireDefault(require("../transform"));
|
|
|
23
23
|
|
|
24
24
|
var _stringConcealing = require("./stringConcealing");
|
|
25
25
|
|
|
26
|
+
var _random = require("../../util/random");
|
|
27
|
+
|
|
26
28
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
29
|
|
|
28
30
|
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; }
|
|
@@ -74,7 +76,7 @@ class StringCompression extends _transform.default {
|
|
|
74
76
|
|
|
75
77
|
_defineProperty(this, "string", void 0);
|
|
76
78
|
|
|
77
|
-
_defineProperty(this, "delimiter", "
|
|
79
|
+
_defineProperty(this, "delimiter", "|");
|
|
78
80
|
|
|
79
81
|
_defineProperty(this, "fnName", void 0);
|
|
80
82
|
|
|
@@ -98,7 +100,7 @@ class StringCompression extends _transform.default {
|
|
|
98
100
|
var encoded = LZ_encode(this.string);
|
|
99
101
|
|
|
100
102
|
if (LZ_decode(encoded) !== this.string) {
|
|
101
|
-
this.error(new Error("String failed to be decoded"));
|
|
103
|
+
this.error(new Error("String failed to be decoded. Try disabling the 'stringCompression' option."));
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
var getStringParamName = this.getPlaceholder();
|
|
@@ -130,33 +132,30 @@ class StringCompression extends _transform.default {
|
|
|
130
132
|
return;
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
if (!(0, _probability.ComputeProbabilityMap)(
|
|
135
|
+
if (!(0, _probability.ComputeProbabilityMap)(this.options.stringCompression, x => x, object.value)) {
|
|
134
136
|
return;
|
|
135
|
-
}
|
|
137
|
+
} // HARD CODED LIMIT of 10,000 (after 1,000 elements)
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
|
|
140
|
+
if (this.map.size > 1000 && !(0, _random.chance)(this.map.size / 100)) return;
|
|
141
|
+
var index = this.map.get(object.value); // New string, add it!
|
|
138
142
|
|
|
139
143
|
if (typeof index !== "number") {
|
|
144
|
+
// Ensure the string gets properly decoded
|
|
140
145
|
if (LZ_decode(LZ_encode(object.value)) !== object.value) {
|
|
141
146
|
this.ignore.add(object.value);
|
|
142
147
|
return;
|
|
143
148
|
}
|
|
144
149
|
|
|
145
|
-
var before = this.string;
|
|
146
150
|
index = this.map.size;
|
|
147
151
|
this.map.set(object.value, index);
|
|
148
|
-
this.string += object.value + this.delimiter;
|
|
149
|
-
|
|
150
|
-
if (LZ_decode(LZ_encode(this.string)) !== this.string) {
|
|
151
|
-
this.string = before;
|
|
152
|
-
this.map.delete(object.value);
|
|
153
|
-
this.ignore.add(object.value);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
152
|
+
this.string += object.value + this.delimiter;
|
|
156
153
|
}
|
|
157
154
|
|
|
158
155
|
(0, _assert.ok)(typeof index === "number");
|
|
159
|
-
|
|
156
|
+
return () => {
|
|
157
|
+
this.replaceIdentifierOrLiteral(object, (0, _gen.CallExpression)((0, _gen.Identifier)(this.fnName), [(0, _gen.Literal)(index)]), parents);
|
|
158
|
+
};
|
|
160
159
|
}
|
|
161
160
|
|
|
162
161
|
}
|
|
@@ -26,6 +26,10 @@ var _transform = _interopRequireDefault(require("../transform"));
|
|
|
26
26
|
|
|
27
27
|
var _encoding = _interopRequireDefault(require("./encoding"));
|
|
28
28
|
|
|
29
|
+
var _probability = require("../../probability");
|
|
30
|
+
|
|
31
|
+
var _bufferToString = require("../../templates/bufferToString");
|
|
32
|
+
|
|
29
33
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
30
34
|
|
|
31
35
|
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; }
|
|
@@ -95,6 +99,11 @@ class StringConcealing extends _transform.default {
|
|
|
95
99
|
apply(tree) {
|
|
96
100
|
super.apply(tree);
|
|
97
101
|
var cacheName = this.getPlaceholder();
|
|
102
|
+
var bufferToStringName = this.getPlaceholder(); // This helper functions convert UInt8 Array to UTf-string
|
|
103
|
+
|
|
104
|
+
(0, _insert.prepend)(tree, ..._bufferToString.BufferToStringTemplate.compile({
|
|
105
|
+
name: bufferToStringName
|
|
106
|
+
}));
|
|
98
107
|
Object.keys(this.encoding).forEach(type => {
|
|
99
108
|
var {
|
|
100
109
|
template
|
|
@@ -102,7 +111,8 @@ class StringConcealing extends _transform.default {
|
|
|
102
111
|
var decodeFn = this.getPlaceholder();
|
|
103
112
|
var getterFn = this.encoding[type];
|
|
104
113
|
(0, _insert.append)(tree, template.single({
|
|
105
|
-
name: decodeFn
|
|
114
|
+
name: decodeFn,
|
|
115
|
+
bufferToString: bufferToStringName
|
|
106
116
|
}));
|
|
107
117
|
(0, _insert.append)(tree, (0, _template.default)("\n \n function ".concat(getterFn, "(x, y, z, a = ").concat(decodeFn, ", b = ").concat(cacheName, "){\n if ( z ) {\n return y[").concat(cacheName, "[z]] = ").concat(getterFn, "(x, y);\n } else if ( y ) {\n [b, y] = [a(b), x || z]\n }\n \n return y ? x[b[y]] : ").concat(cacheName, "[x] || (z=(b[x], a), ").concat(cacheName, "[x] = z(").concat(this.arrayName, "[x]))\n }\n \n ")).single());
|
|
108
118
|
});
|
|
@@ -122,12 +132,19 @@ class StringConcealing extends _transform.default {
|
|
|
122
132
|
// Empty strings are discarded
|
|
123
133
|
if (!object.value || this.ignore.has(object.value) || object.value.length == 0) {
|
|
124
134
|
return;
|
|
125
|
-
}
|
|
135
|
+
} // Allow user to choose which strings get changed
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if (!(0, _probability.ComputeProbabilityMap)(this.options.stringConcealing, x => x, object.value)) {
|
|
139
|
+
return;
|
|
140
|
+
} // HARD CODED LIMIT of 10,000 (after 1,000 elements)
|
|
141
|
+
|
|
126
142
|
|
|
143
|
+
if (this.set.size > 1000 && !(0, _random.chance)(this.set.size / 100)) return;
|
|
127
144
|
var types = Object.keys(this.encoding);
|
|
128
145
|
var type = (0, _random.choice)(types);
|
|
129
146
|
|
|
130
|
-
if (!type || !this.hasAllEncodings &&
|
|
147
|
+
if (!type || !this.hasAllEncodings && (0, _random.chance)(10)) {
|
|
131
148
|
var allowed = Object.keys(_encoding.default).filter(type => !this.encoding[type]);
|
|
132
149
|
|
|
133
150
|
if (!allowed.length) {
|
|
@@ -165,16 +182,16 @@ class StringConcealing extends _transform.default {
|
|
|
165
182
|
(0, _assert.ok)(index != -1, "index == -1");
|
|
166
183
|
var callExpr = (0, _gen.CallExpression)((0, _gen.Identifier)(fnName), [(0, _gen.Literal)(index)]); // use `.apply` to fool automated de-obfuscators
|
|
167
184
|
|
|
168
|
-
if (
|
|
169
|
-
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.
|
|
185
|
+
if ((0, _random.chance)(10)) {
|
|
186
|
+
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Literal)("apply"), true), [(0, _gen.Identifier)("undefined"), (0, _gen.ArrayExpression)([(0, _gen.Literal)(index)])]);
|
|
170
187
|
} // use `.call`
|
|
171
|
-
else if (
|
|
172
|
-
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.
|
|
188
|
+
else if ((0, _random.chance)(10)) {
|
|
189
|
+
callExpr = (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(fnName), (0, _gen.Literal)("call"), true), [(0, _gen.Identifier)("undefined"), (0, _gen.Literal)(index)]);
|
|
173
190
|
}
|
|
174
191
|
|
|
175
192
|
var referenceType = "call";
|
|
176
193
|
|
|
177
|
-
if (parents.length &&
|
|
194
|
+
if (parents.length && (0, _random.chance)(50 - this.variablesMade)) {
|
|
178
195
|
referenceType = "constantReference";
|
|
179
196
|
}
|
|
180
197
|
|
|
@@ -9,15 +9,15 @@ var _transform = _interopRequireDefault(require("../transform"));
|
|
|
9
9
|
|
|
10
10
|
var _random = require("../../util/random");
|
|
11
11
|
|
|
12
|
-
var _order = require("../../order");
|
|
13
|
-
|
|
14
12
|
var _compare = require("../../util/compare");
|
|
15
13
|
|
|
16
14
|
var _stringConcealing = require("./stringConcealing");
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
var _probability = require("../../probability");
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
var _gen = require("../../util/gen");
|
|
19
|
+
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
21
|
|
|
22
22
|
function pad(x, len) {
|
|
23
23
|
while (x.length < len) {
|
|
@@ -73,34 +73,23 @@ function toUnicodeRepresentation(str) {
|
|
|
73
73
|
|
|
74
74
|
class StringEncoding extends _transform.default {
|
|
75
75
|
constructor(o) {
|
|
76
|
-
super(o
|
|
77
|
-
|
|
78
|
-
_defineProperty(this, "seen", void 0);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
apply(tree) {
|
|
82
|
-
this.seen = new Set();
|
|
83
|
-
super.apply(tree);
|
|
76
|
+
super(o);
|
|
84
77
|
}
|
|
85
78
|
|
|
86
79
|
match(object, parents) {
|
|
87
|
-
return object.type == "Literal" && typeof object.value === "string" && !(0, _stringConcealing.isModuleSource)(object, parents) && !(0, _compare.isDirective)(object, parents);
|
|
80
|
+
return object.type == "Literal" && typeof object.value === "string" && object.value.length > 0 && !(0, _stringConcealing.isModuleSource)(object, parents) && !(0, _compare.isDirective)(object, parents);
|
|
88
81
|
}
|
|
89
82
|
|
|
90
83
|
transform(object, parents) {
|
|
91
|
-
//
|
|
92
|
-
if (this.
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
this.seen.add(object);
|
|
84
|
+
// Allow percentages
|
|
85
|
+
if (!(0, _probability.ComputeProbabilityMap)(this.options.stringEncoding, x => x, object.value)) return;
|
|
97
86
|
var type = (0, _random.choice)(["hexadecimal", "unicode"]);
|
|
98
|
-
var escapedString = (type == "hexadecimal" ? toHexRepresentation : toUnicodeRepresentation)(object.value);
|
|
87
|
+
var escapedString = (type == "hexadecimal" ? toHexRepresentation : toUnicodeRepresentation)(object.value);
|
|
88
|
+
return () => {
|
|
89
|
+
if (object.type !== "Literal") return; // ESCodeGen tries to escape backslashes, here is a work-around
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
name: "'".concat(escapedString, "'")
|
|
103
|
-
});
|
|
91
|
+
this.replace(object, (0, _gen.Identifier)("'".concat(escapedString, "'")));
|
|
92
|
+
};
|
|
104
93
|
}
|
|
105
94
|
|
|
106
95
|
}
|
|
@@ -81,10 +81,6 @@ class Transform {
|
|
|
81
81
|
/**
|
|
82
82
|
* Transforms to run after.
|
|
83
83
|
*/
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Transformations to run at the same time (can cause conflicts so use sparingly)
|
|
87
|
-
*/
|
|
88
84
|
constructor(obfuscator) {
|
|
89
85
|
let priority = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
|
|
90
86
|
|
|
@@ -98,15 +94,12 @@ class Transform {
|
|
|
98
94
|
|
|
99
95
|
_defineProperty(this, "after", void 0);
|
|
100
96
|
|
|
101
|
-
_defineProperty(this, "concurrent", void 0);
|
|
102
|
-
|
|
103
97
|
(0, _assert.ok)(obfuscator instanceof _obfuscator.default, "obfuscator should be an Obfuscator");
|
|
104
98
|
this.obfuscator = obfuscator;
|
|
105
99
|
this.options = this.obfuscator.options;
|
|
106
100
|
this.priority = priority;
|
|
107
101
|
this.before = [];
|
|
108
102
|
this.after = [];
|
|
109
|
-
this.concurrent = [];
|
|
110
103
|
}
|
|
111
104
|
/**
|
|
112
105
|
* The transformation name.
|
|
@@ -136,12 +129,12 @@ class Transform {
|
|
|
136
129
|
|
|
137
130
|
|
|
138
131
|
this.before.forEach(x => x.apply(tree));
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Run this transformation
|
|
134
|
+
*/
|
|
142
135
|
|
|
143
|
-
|
|
144
|
-
return
|
|
136
|
+
(0, _traverse.default)(tree, (object, parents) => {
|
|
137
|
+
return this.input(object, parents);
|
|
145
138
|
});
|
|
146
139
|
/**
|
|
147
140
|
* Cleanup transformations
|
|
@@ -202,18 +195,17 @@ class Transform {
|
|
|
202
195
|
getPlaceholder() {
|
|
203
196
|
const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 10).toString(10)).join("");
|
|
204
197
|
|
|
205
|
-
return
|
|
198
|
+
return _constants.placeholderVariablePrefix + genRanHex(10);
|
|
206
199
|
}
|
|
207
200
|
/**
|
|
208
201
|
* Returns an independent name generator with it's own counter.
|
|
209
|
-
* @param
|
|
202
|
+
* @param overrideMode - Override the user's `identifierGenerator` option
|
|
210
203
|
* @returns
|
|
211
204
|
*/
|
|
212
205
|
|
|
213
206
|
|
|
214
|
-
getGenerator() {
|
|
215
|
-
|
|
216
|
-
var count = offset;
|
|
207
|
+
getGenerator(overrideMode) {
|
|
208
|
+
var count = 0;
|
|
217
209
|
var identifiers = new Set();
|
|
218
210
|
return {
|
|
219
211
|
generate: () => {
|
|
@@ -221,7 +213,7 @@ class Transform {
|
|
|
221
213
|
|
|
222
214
|
do {
|
|
223
215
|
count++;
|
|
224
|
-
retValue = this.generateIdentifier(-1, count);
|
|
216
|
+
retValue = this.generateIdentifier(-1, count, overrideMode);
|
|
225
217
|
} while (identifiers.has(retValue));
|
|
226
218
|
|
|
227
219
|
identifiers.add(retValue);
|
|
@@ -239,6 +231,7 @@ class Transform {
|
|
|
239
231
|
generateIdentifier() {
|
|
240
232
|
let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1;
|
|
241
233
|
let count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
|
|
234
|
+
let overrideMode = arguments.length > 2 ? arguments[2] : undefined;
|
|
242
235
|
|
|
243
236
|
if (length == -1) {
|
|
244
237
|
length = (0, _random.getRandomInteger)(6, 8);
|
|
@@ -255,7 +248,7 @@ class Transform {
|
|
|
255
248
|
var identifier;
|
|
256
249
|
|
|
257
250
|
do {
|
|
258
|
-
identifier = (0, _probability.ComputeProbabilityMap)(this.options.identifierGenerator, function () {
|
|
251
|
+
identifier = (0, _probability.ComputeProbabilityMap)(overrideMode || this.options.identifierGenerator, function () {
|
|
259
252
|
let mode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "randomized";
|
|
260
253
|
|
|
261
254
|
switch (mode) {
|
package/dist/traverse.js
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.assertNoCircular = assertNoCircular;
|
|
6
7
|
exports.default = traverse;
|
|
7
8
|
exports.getBlock = getBlock;
|
|
8
9
|
exports.isBlock = isBlock;
|
|
9
10
|
exports.walk = walk;
|
|
10
11
|
|
|
11
|
-
var _identifiers = require("./util/identifiers");
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* A block refers to any object that has a **`.body`** property where code is nested.
|
|
15
14
|
*
|
|
@@ -41,12 +40,10 @@ function isBlock(object) {
|
|
|
41
40
|
|
|
42
41
|
function walk(object, parents, onEnter) {
|
|
43
42
|
if (typeof object === "object" && object) {
|
|
44
|
-
var newParents = [object, ...parents];
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
} // 1. Call `onEnter` function and remember any onExit callback returned
|
|
49
|
-
|
|
43
|
+
var newParents = [object, ...parents]; // if (!Array.isArray(object)) {
|
|
44
|
+
// validateChain(object, parents);
|
|
45
|
+
// }
|
|
46
|
+
// 1. Call `onEnter` function and remember any onExit callback returned
|
|
50
47
|
|
|
51
48
|
var onExit = onEnter(object, parents); // 2. Traverse children
|
|
52
49
|
|
|
@@ -58,8 +55,6 @@ function walk(object, parents, onEnter) {
|
|
|
58
55
|
return "EXIT";
|
|
59
56
|
}
|
|
60
57
|
}
|
|
61
|
-
|
|
62
|
-
copy.forEach(x => {});
|
|
63
58
|
} else {
|
|
64
59
|
var keys = Object.keys(object);
|
|
65
60
|
|
|
@@ -100,4 +95,23 @@ function walk(object, parents, onEnter) {
|
|
|
100
95
|
|
|
101
96
|
function traverse(tree, onEnter) {
|
|
102
97
|
walk(tree, [], onEnter);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* This is debugging function used to test for circular references.
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
function assertNoCircular(object) {
|
|
105
|
+
var seen = new Set();
|
|
106
|
+
traverse(object, (node, nodeParents) => {
|
|
107
|
+
if (node && typeof node === "object") {
|
|
108
|
+
if (seen.has(node)) {
|
|
109
|
+
console.log(nodeParents);
|
|
110
|
+
console.log(node);
|
|
111
|
+
throw new Error("FOUND CIRCULAR REFERENCE");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
seen.add(node);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
103
117
|
}
|
package/dist/util/gen.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.BreakStatement = BreakStatement;
|
|
|
15
15
|
exports.CallExpression = CallExpression;
|
|
16
16
|
exports.CatchClause = CatchClause;
|
|
17
17
|
exports.ClassDeclaration = ClassDeclaration;
|
|
18
|
+
exports.ClassExpression = ClassExpression;
|
|
18
19
|
exports.ConditionalExpression = ConditionalExpression;
|
|
19
20
|
exports.DebuggerStatement = DebuggerStatement;
|
|
20
21
|
exports.ExpressionStatement = ExpressionStatement;
|
|
@@ -174,6 +175,7 @@ function BreakStatement(label) {
|
|
|
174
175
|
|
|
175
176
|
function Property(key, value) {
|
|
176
177
|
let computed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
178
|
+
let kind = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "init";
|
|
177
179
|
|
|
178
180
|
if (!key) {
|
|
179
181
|
throw new Error("key is undefined");
|
|
@@ -188,7 +190,7 @@ function Property(key, value) {
|
|
|
188
190
|
key: key,
|
|
189
191
|
computed: computed,
|
|
190
192
|
value: value,
|
|
191
|
-
kind:
|
|
193
|
+
kind: kind,
|
|
192
194
|
method: false,
|
|
193
195
|
shorthand: false
|
|
194
196
|
};
|
|
@@ -537,6 +539,20 @@ function ClassDeclaration(id) {
|
|
|
537
539
|
};
|
|
538
540
|
}
|
|
539
541
|
|
|
542
|
+
function ClassExpression(id) {
|
|
543
|
+
let superClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
544
|
+
let body = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
545
|
+
return {
|
|
546
|
+
type: "ClassExpression",
|
|
547
|
+
id: id,
|
|
548
|
+
superClass: superClass,
|
|
549
|
+
body: {
|
|
550
|
+
type: "ClassBody",
|
|
551
|
+
body: body
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
540
556
|
function ThrowStatement(argument) {
|
|
541
557
|
return {
|
|
542
558
|
type: "ThrowStatement",
|
package/dist/util/identifiers.js
CHANGED
|
@@ -42,6 +42,22 @@ function validateChain(object, parents) {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
function objectPatternCheck(object, parents) {
|
|
47
|
+
var objectPatternIndex = parents.findIndex(x => x.type === "ObjectPattern");
|
|
48
|
+
|
|
49
|
+
if (objectPatternIndex == -1) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var property = parents[objectPatternIndex].properties.find(property => parents[objectPatternIndex - 2] === property);
|
|
54
|
+
|
|
55
|
+
if (property.key === (parents[objectPatternIndex - 3] || object)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
45
61
|
/**
|
|
46
62
|
* Returns detailed information about the given Identifier node.
|
|
47
63
|
* @param object
|
|
@@ -70,11 +86,29 @@ function getIdentifierInfo(object, parents) {
|
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
var varIndex = parents.findIndex(x => x.type == "VariableDeclarator");
|
|
73
|
-
var isVariableDeclaration = varIndex != -1 && parents[varIndex].id == (parents[varIndex - 1] || object) && parents.find(x => x.type == "VariableDeclaration");
|
|
89
|
+
var isVariableDeclaration = varIndex != -1 && parents[varIndex].id == (parents[varIndex - 1] || object) && parents.find(x => x.type == "VariableDeclaration") && objectPatternCheck(object, parents); // Assignment pattern check!
|
|
90
|
+
|
|
91
|
+
if (isVariableDeclaration) {
|
|
92
|
+
var slicedParents = parents.slice(0, varIndex - 1);
|
|
93
|
+
var i = 0;
|
|
94
|
+
|
|
95
|
+
for (var parent of slicedParents) {
|
|
96
|
+
var childNode = slicedParents[i - 1] || object;
|
|
97
|
+
|
|
98
|
+
if (parent.type === "AssignmentPattern" && parent.right === childNode) {
|
|
99
|
+
isVariableDeclaration = false;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
i++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
74
107
|
var forIndex = parents.findIndex(x => x.type == "ForStatement");
|
|
75
108
|
var isForInitializer = forIndex != -1 && parents[forIndex].init == (parents[forIndex - 1] || object);
|
|
76
109
|
var functionIndex = parents.findIndex(x => (0, _insert.isFunction)(x));
|
|
77
110
|
var isFunctionDeclaration = functionIndex != -1 && parents[functionIndex].type == "FunctionDeclaration" && parents[functionIndex].id == object;
|
|
111
|
+
var isNamedFunctionExpression = functionIndex != -1 && parents[functionIndex].type === "FunctionExpression" && parents[functionIndex].id === object;
|
|
78
112
|
var isAFunctionParameter = isFunctionParameter(object, parents);
|
|
79
113
|
var isClauseParameter = false; // Special case for Catch clauses
|
|
80
114
|
|
|
@@ -90,7 +124,7 @@ function getIdentifierInfo(object, parents) {
|
|
|
90
124
|
var isFunctionCall = parent.callee == object; // NewExpression and CallExpression
|
|
91
125
|
|
|
92
126
|
var assignmentIndex = parents.findIndex(p => p.type === "AssignmentExpression");
|
|
93
|
-
var isAssignmentLeft = assignmentIndex !== -1 && parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object);
|
|
127
|
+
var isAssignmentLeft = assignmentIndex !== -1 && parents[assignmentIndex].left === (parents[assignmentIndex - 1] || object) && objectPatternCheck(object, parents);
|
|
94
128
|
var isAssignmentValue = assignmentIndex !== -1 && parents[assignmentIndex].right === (parents[assignmentIndex - 1] || object);
|
|
95
129
|
var isUpdateExpression = parent.type == "UpdateExpression";
|
|
96
130
|
var isClassDeclaration = (parent.type == "ClassDeclaration" || parent.type == "ClassExpression") && parent.id == object;
|
|
@@ -227,7 +261,7 @@ function getIdentifierInfo(object, parents) {
|
|
|
227
261
|
/**
|
|
228
262
|
* Is the Identifier defined, i.e a variable declaration, function declaration, parameter, or class definition
|
|
229
263
|
*/
|
|
230
|
-
isDefined: isVariableDeclaration || isFunctionDeclaration || isAFunctionParameter || isClassDeclaration || isClauseParameter || isMethodDefinition || isImportSpecifier,
|
|
264
|
+
isDefined: isVariableDeclaration || isFunctionDeclaration || isNamedFunctionExpression || isAFunctionParameter || isClassDeclaration || isClauseParameter || isMethodDefinition || isImportSpecifier,
|
|
231
265
|
|
|
232
266
|
/**
|
|
233
267
|
* Is the Identifier modified, either by an `AssignmentExpression` or `UpdateExpression`
|
package/dist/util/insert.js
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.append = append;
|
|
7
7
|
exports.clone = clone;
|
|
8
|
+
exports.computeFunctionLength = computeFunctionLength;
|
|
8
9
|
exports.deleteDeclaration = deleteDeclaration;
|
|
9
10
|
exports.deleteDirect = deleteDirect;
|
|
10
11
|
exports.getAllDefiningContexts = getAllDefiningContexts;
|
|
@@ -168,15 +169,14 @@ function getAllDefiningContexts(o, p) {
|
|
|
168
169
|
|
|
169
170
|
if (info.isFunctionParameter) {
|
|
170
171
|
// Get Function
|
|
171
|
-
var fn = getFunction(o, p);
|
|
172
|
-
contexts.push(fn.body);
|
|
172
|
+
var fn = getFunction(o, p); // contexts.push(fn.body);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
if (info.isClauseParameter) {
|
|
176
176
|
var catchClause = p.find(x => x.type === "CatchClause");
|
|
177
177
|
|
|
178
178
|
if (catchClause) {
|
|
179
|
-
|
|
179
|
+
return [catchClause];
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
|
|
@@ -306,8 +306,18 @@ function prepend(block) {
|
|
|
306
306
|
}
|
|
307
307
|
});
|
|
308
308
|
block.body.splice(moveBy, 0, ...nodes);
|
|
309
|
+
} else if (block.type === "SwitchCase") {
|
|
310
|
+
block.consequent.unshift(...nodes);
|
|
309
311
|
} else {
|
|
310
|
-
getBlockBody(block)
|
|
312
|
+
var bodyArray = getBlockBody(block); // Check for 'use strict'
|
|
313
|
+
|
|
314
|
+
if (bodyArray[0] && bodyArray[0].directive) {
|
|
315
|
+
// Insert under 'use strict' directive
|
|
316
|
+
bodyArray.splice(1, 0, ...nodes);
|
|
317
|
+
} else {
|
|
318
|
+
// Prepend at the top of the block
|
|
319
|
+
bodyArray.unshift(...nodes);
|
|
320
|
+
}
|
|
311
321
|
}
|
|
312
322
|
}
|
|
313
323
|
|
|
@@ -378,4 +388,25 @@ function isForInitialize(o, p) {
|
|
|
378
388
|
}
|
|
379
389
|
|
|
380
390
|
return false;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Computes the `function.length` property given the parameter nodes.
|
|
394
|
+
*
|
|
395
|
+
* @param params
|
|
396
|
+
* @returns
|
|
397
|
+
*/
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
function computeFunctionLength(params) {
|
|
401
|
+
var count = 0;
|
|
402
|
+
|
|
403
|
+
for (var parameterNode of params) {
|
|
404
|
+
if (parameterNode.type === "Identifier" || parameterNode.type === "ObjectPattern" || parameterNode.type === "ArrayPattern") {
|
|
405
|
+
count++;
|
|
406
|
+
} else {
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return count;
|
|
381
412
|
}
|
package/dist/util/random.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.alphabeticalGenerator = alphabeticalGenerator;
|
|
7
|
+
exports.chance = chance;
|
|
7
8
|
exports.choice = choice;
|
|
8
9
|
exports.getRandom = getRandom;
|
|
9
10
|
exports.getRandomFalseExpression = getRandomFalseExpression;
|
|
@@ -17,10 +18,24 @@ var _assert = require("assert");
|
|
|
17
18
|
|
|
18
19
|
var _gen = require("./gen");
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Returns a random element from the given array
|
|
23
|
+
* @param choices Array of items
|
|
24
|
+
* @returns One of the items in the array at random
|
|
25
|
+
*/
|
|
20
26
|
function choice(choices) {
|
|
21
27
|
var index = Math.floor(Math.random() * choices.length);
|
|
22
28
|
return choices[index];
|
|
23
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns a true/false based on the percent chance (0%-100%)
|
|
32
|
+
* @param percentChance AS A PERCENTAGE 0 - 100%
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
function chance(percentChance) {
|
|
37
|
+
return Math.random() < percentChance / 100;
|
|
38
|
+
}
|
|
24
39
|
/**
|
|
25
40
|
* **Mutates the given array**
|
|
26
41
|
* @param array
|