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.
- package/CHANGELOG.md +38 -0
- package/README.md +12 -27
- package/dist/compiler.js +2 -8
- package/dist/constants.js +17 -10
- package/dist/index.js +7 -30
- package/dist/obfuscator.js +15 -62
- package/dist/options.js +21 -38
- package/dist/order.js +4 -7
- package/dist/parser.js +5 -13
- package/dist/precedence.js +6 -8
- package/dist/presets.js +4 -6
- package/dist/probability.js +13 -24
- package/dist/templates/bufferToString.js +100 -5
- package/dist/templates/crash.js +51 -9
- package/dist/templates/es5.js +125 -6
- package/dist/templates/functionLength.js +24 -6
- package/dist/templates/globals.js +9 -0
- package/dist/templates/template.js +71 -30
- package/dist/transforms/antiTooling.js +26 -22
- package/dist/transforms/calculator.js +18 -54
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +236 -333
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
- package/dist/transforms/deadCode.js +528 -27
- package/dist/transforms/dispatcher.js +106 -110
- package/dist/transforms/es5/antiClass.js +70 -44
- package/dist/transforms/es5/antiDestructuring.js +14 -38
- package/dist/transforms/es5/antiES6Object.js +39 -48
- package/dist/transforms/es5/antiSpreadOperator.js +5 -14
- package/dist/transforms/es5/antiTemplate.js +10 -19
- package/dist/transforms/es5/es5.js +7 -40
- package/dist/transforms/extraction/classExtraction.js +83 -0
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
- package/dist/transforms/extraction/objectExtraction.js +24 -56
- package/dist/transforms/finalizer.js +6 -20
- package/dist/transforms/flatten.js +51 -99
- package/dist/transforms/identifier/globalAnalysis.js +8 -26
- package/dist/transforms/identifier/globalConcealing.js +35 -54
- package/dist/transforms/identifier/movedDeclarations.js +66 -38
- package/dist/transforms/identifier/renameVariables.js +29 -68
- package/dist/transforms/identifier/variableAnalysis.js +21 -48
- package/dist/transforms/lock/antiDebug.js +20 -25
- package/dist/transforms/lock/integrity.js +48 -47
- package/dist/transforms/lock/lock.js +62 -113
- package/dist/transforms/minify.js +77 -108
- package/dist/transforms/opaquePredicates.js +11 -48
- package/dist/transforms/preparation.js +17 -50
- package/dist/transforms/renameLabels.js +5 -22
- package/dist/transforms/rgf.js +93 -69
- package/dist/transforms/shuffle.js +41 -46
- package/dist/transforms/stack.js +35 -98
- package/dist/transforms/string/encoding.js +73 -27
- package/dist/transforms/string/stringCompression.js +44 -68
- package/dist/transforms/string/stringConcealing.js +125 -134
- package/dist/transforms/string/stringEncoding.js +6 -26
- package/dist/transforms/string/stringSplitting.js +5 -30
- package/dist/transforms/transform.js +50 -100
- package/dist/traverse.js +11 -18
- package/dist/util/compare.js +27 -29
- package/dist/util/gen.js +32 -86
- package/dist/util/guard.js +0 -1
- package/dist/util/identifiers.js +9 -72
- package/dist/util/insert.js +27 -77
- package/dist/util/math.js +0 -3
- package/dist/util/object.js +3 -7
- package/dist/util/random.js +5 -36
- package/dist/util/scope.js +6 -3
- package/package.json +3 -3
- package/src/constants.ts +12 -0
- package/src/options.ts +13 -0
- package/src/order.ts +2 -2
- package/src/templates/bufferToString.ts +49 -11
- package/src/templates/functionLength.ts +21 -3
- package/src/templates/globals.ts +3 -0
- package/src/templates/template.ts +85 -25
- package/src/transforms/antiTooling.ts +33 -11
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +2 -2
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
- package/src/transforms/deadCode.ts +0 -16
- package/src/transforms/dispatcher.ts +91 -69
- package/src/transforms/es5/antiClass.ts +10 -1
- package/src/transforms/extraction/classExtraction.ts +168 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -10
- package/src/transforms/extraction/objectExtraction.ts +4 -15
- package/src/transforms/flatten.ts +20 -5
- package/src/transforms/identifier/globalConcealing.ts +29 -65
- package/src/transforms/identifier/movedDeclarations.ts +90 -24
- package/src/transforms/minify.ts +27 -12
- package/src/transforms/rgf.ts +94 -5
- package/src/transforms/stack.ts +12 -3
- package/src/transforms/string/encoding.ts +85 -51
- package/src/transforms/string/stringCompression.ts +5 -8
- package/src/transforms/string/stringConcealing.ts +139 -113
- package/src/transforms/string/stringEncoding.ts +1 -2
- package/src/transforms/string/stringSplitting.ts +1 -2
- package/src/transforms/transform.ts +30 -1
- package/src/util/compare.ts +39 -5
- package/src/util/gen.ts +10 -3
- package/src/util/insert.ts +17 -0
- package/src/util/scope.ts +14 -2
- package/test/code/Cash.test.ts +10 -4
- package/test/code/StrictMode.src.js +65 -0
- package/test/code/StrictMode.test.js +37 -0
- package/test/compare.test.ts +62 -2
- package/test/options.test.ts +111 -55
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
- package/test/transforms/dispatcher.test.ts +55 -0
- package/test/transforms/extraction/classExtraction.test.ts +86 -0
- package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
- package/test/transforms/extraction/objectExtraction.test.ts +2 -0
- package/test/transforms/identifier/globalConcealing.test.ts +19 -0
- package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
- package/test/transforms/minify.test.ts +37 -0
- package/test/transforms/rgf.test.ts +50 -0
- package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
- package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
- package/dist/transforms/eval.js +0 -84
- package/dist/transforms/hexadecimalNumbers.js +0 -63
- package/dist/transforms/hideInitializingCode.js +0 -270
- package/dist/transforms/identifier/nameRecycling.js +0 -218
- package/dist/transforms/label.js +0 -67
- package/dist/transforms/preparation/nameConflicts.js +0 -116
- package/dist/transforms/preparation/preparation.js +0 -188
|
@@ -4,62 +4,103 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = Template;
|
|
7
|
-
|
|
8
7
|
var _parser = require("../parser");
|
|
8
|
+
var _assert = require("assert");
|
|
9
|
+
var _random = require("../util/random");
|
|
10
|
+
var _constants = require("../constants");
|
|
11
|
+
function Template() {
|
|
12
|
+
for (var _len = arguments.length, templates = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
13
|
+
templates[_key] = arguments[_key];
|
|
14
|
+
}
|
|
15
|
+
(0, _assert.ok)(templates.length);
|
|
16
|
+
var requiredVariables = new Set();
|
|
17
|
+
var providedVariables = {};
|
|
18
|
+
var defaultVariables = Object.create(null);
|
|
9
19
|
|
|
10
|
-
|
|
11
|
-
|
|
20
|
+
// This may picked up "$mb[pP`x]" from String Encoding function
|
|
21
|
+
// ignoreMissingVariables() prevents this
|
|
22
|
+
var matches = templates[0].match(/{[$A-z0-9_]+}/g);
|
|
23
|
+
if (matches !== null) {
|
|
24
|
+
matches.forEach(variable => {
|
|
25
|
+
var name = variable.slice(1, -1);
|
|
12
26
|
|
|
13
|
-
|
|
14
|
-
|
|
27
|
+
// $ variables are for default variables
|
|
28
|
+
if (name.startsWith("$")) {
|
|
29
|
+
defaultVariables[name] = _constants.placeholderVariablePrefix + "td_" + Object.keys(defaultVariables).length;
|
|
30
|
+
} else {
|
|
31
|
+
requiredVariables.add(name);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
15
34
|
}
|
|
35
|
+
function fill() {
|
|
36
|
+
let variables = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Object.create(null);
|
|
37
|
+
var userVariables = {
|
|
38
|
+
...providedVariables,
|
|
39
|
+
...variables
|
|
40
|
+
};
|
|
16
41
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
function fill(variables) {
|
|
23
|
-
if (!variables) {
|
|
24
|
-
variables = Object.create(null);
|
|
42
|
+
// Validate all variables were passed in
|
|
43
|
+
for (var requiredVariable of requiredVariables) {
|
|
44
|
+
if (typeof userVariables[requiredVariable] === "undefined") {
|
|
45
|
+
throw new Error(templates[0] + " missing variable: " + requiredVariable + " from " + JSON.stringify(userVariables));
|
|
46
|
+
}
|
|
25
47
|
}
|
|
26
|
-
|
|
27
|
-
var
|
|
28
|
-
var
|
|
29
|
-
...
|
|
48
|
+
var template = (0, _random.choice)(templates);
|
|
49
|
+
var output = template;
|
|
50
|
+
var allVariables = {
|
|
51
|
+
...defaultVariables,
|
|
52
|
+
...userVariables
|
|
30
53
|
};
|
|
31
|
-
Object.keys(
|
|
32
|
-
var bracketName = "{" + name + "}";
|
|
33
|
-
var value =
|
|
54
|
+
Object.keys(allVariables).forEach(name => {
|
|
55
|
+
var bracketName = "{" + name.replace("$", "\\$") + "}";
|
|
56
|
+
var value = allVariables[name] + "";
|
|
34
57
|
var reg = new RegExp(bracketName, "g");
|
|
35
|
-
|
|
58
|
+
output = output.replace(reg, value);
|
|
36
59
|
});
|
|
37
|
-
return
|
|
60
|
+
return {
|
|
61
|
+
output,
|
|
62
|
+
template
|
|
63
|
+
};
|
|
38
64
|
}
|
|
39
|
-
|
|
40
65
|
function compile(variables) {
|
|
41
|
-
var
|
|
42
|
-
|
|
66
|
+
var {
|
|
67
|
+
output,
|
|
68
|
+
template
|
|
69
|
+
} = fill(variables);
|
|
43
70
|
try {
|
|
44
|
-
var program = (0, _parser.parseSnippet)(
|
|
71
|
+
var program = (0, _parser.parseSnippet)(output);
|
|
45
72
|
return program.body;
|
|
46
73
|
} catch (e) {
|
|
47
74
|
console.error(e);
|
|
48
75
|
console.error(template);
|
|
49
|
-
|
|
76
|
+
console.error({
|
|
77
|
+
...providedVariables,
|
|
78
|
+
...variables
|
|
79
|
+
});
|
|
80
|
+
throw new Error("Template failed to parse: OUTPUT= " + output + " SOURCE= " + template);
|
|
50
81
|
}
|
|
51
82
|
}
|
|
52
|
-
|
|
53
83
|
function single(variables) {
|
|
54
84
|
var nodes = compile(variables);
|
|
55
85
|
return nodes[0];
|
|
56
86
|
}
|
|
57
|
-
|
|
87
|
+
function variables(newVariables) {
|
|
88
|
+
Object.assign(providedVariables, newVariables);
|
|
89
|
+
return obj;
|
|
90
|
+
}
|
|
91
|
+
function ignoreMissingVariables() {
|
|
92
|
+
defaultVariables = Object.create(null);
|
|
93
|
+
requiredVariables.clear();
|
|
94
|
+
return obj;
|
|
95
|
+
}
|
|
58
96
|
var obj = {
|
|
59
97
|
fill,
|
|
60
98
|
compile,
|
|
61
99
|
single,
|
|
62
|
-
|
|
100
|
+
templates,
|
|
101
|
+
variables,
|
|
102
|
+
ignoreMissingVariables,
|
|
103
|
+
source: templates[0]
|
|
63
104
|
};
|
|
64
105
|
return obj;
|
|
65
106
|
}
|
|
@@ -4,35 +4,41 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
var _order = require("../order");
|
|
9
|
-
|
|
8
|
+
var _template = _interopRequireDefault(require("../templates/template"));
|
|
10
9
|
var _traverse = require("../traverse");
|
|
11
|
-
|
|
12
10
|
var _gen = require("../util/gen");
|
|
13
|
-
|
|
14
|
-
var _random = require("../util/random");
|
|
15
|
-
|
|
11
|
+
var _insert = require("../util/insert");
|
|
16
12
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
17
|
-
|
|
18
|
-
function
|
|
19
|
-
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
15
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
16
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
20
17
|
// JsNice.org tries to separate sequence expressions into multiple lines, this stops that.
|
|
21
18
|
class AntiTooling extends _transform.default {
|
|
22
19
|
constructor(o) {
|
|
23
20
|
super(o, _order.ObfuscateOrder.AntiTooling);
|
|
21
|
+
_defineProperty(this, "fnName", void 0);
|
|
22
|
+
}
|
|
23
|
+
apply(tree) {
|
|
24
|
+
super.apply(tree);
|
|
25
|
+
if (typeof this.fnName === "string") {
|
|
26
|
+
(0, _insert.prepend)(tree, (0, _template.default)(`
|
|
27
|
+
function {fnName}(){
|
|
28
|
+
}
|
|
29
|
+
`).single({
|
|
30
|
+
fnName: this.fnName
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
24
33
|
}
|
|
25
|
-
|
|
26
34
|
match(object, parents) {
|
|
27
35
|
return (0, _traverse.isBlock)(object) || object.type == "SwitchCase";
|
|
28
36
|
}
|
|
29
|
-
|
|
30
37
|
transform(object, parents) {
|
|
31
38
|
return () => {
|
|
32
39
|
var exprs = [];
|
|
33
40
|
var deleteExprs = [];
|
|
34
41
|
var body = object.type == "SwitchCase" ? object.consequent : object.body;
|
|
35
|
-
|
|
36
42
|
const end = () => {
|
|
37
43
|
function flatten(expr) {
|
|
38
44
|
if (expr.type == "ExpressionStatement") {
|
|
@@ -43,25 +49,26 @@ class AntiTooling extends _transform.default {
|
|
|
43
49
|
flattened.push(expr);
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
|
-
|
|
47
52
|
var flattened = [];
|
|
48
53
|
exprs.forEach(flatten);
|
|
49
|
-
|
|
50
54
|
if (flattened.length > 1) {
|
|
51
|
-
flattened[0] = {
|
|
55
|
+
flattened[0] = {
|
|
56
|
+
...flattened[0]
|
|
52
57
|
};
|
|
53
|
-
|
|
58
|
+
if (!this.fnName) {
|
|
59
|
+
this.fnName = this.getPlaceholder();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// (expr1,expr2,expr3) -> F(expr1, expr2, expr3)
|
|
63
|
+
this.replace(exprs[0], (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.fnName), [...flattened])));
|
|
54
64
|
deleteExprs.push(...exprs.slice(1));
|
|
55
65
|
}
|
|
56
|
-
|
|
57
66
|
exprs = [];
|
|
58
67
|
};
|
|
59
|
-
|
|
60
68
|
body.forEach((stmt, i) => {
|
|
61
69
|
if (stmt.hidden || stmt.directive) {
|
|
62
70
|
return;
|
|
63
71
|
}
|
|
64
|
-
|
|
65
72
|
if (stmt.type == "ExpressionStatement") {
|
|
66
73
|
exprs.push(stmt);
|
|
67
74
|
} else {
|
|
@@ -71,14 +78,11 @@ class AntiTooling extends _transform.default {
|
|
|
71
78
|
end();
|
|
72
79
|
deleteExprs.forEach(expr => {
|
|
73
80
|
var index = body.indexOf(expr);
|
|
74
|
-
|
|
75
81
|
if (index !== -1) {
|
|
76
82
|
body.splice(index, 1);
|
|
77
83
|
}
|
|
78
84
|
});
|
|
79
85
|
};
|
|
80
86
|
}
|
|
81
|
-
|
|
82
87
|
}
|
|
83
|
-
|
|
84
88
|
exports.default = AntiTooling;
|
|
@@ -4,48 +4,30 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
9
|
-
|
|
10
8
|
var _gen = require("../util/gen");
|
|
11
|
-
|
|
12
9
|
var _insert = require("../util/insert");
|
|
13
|
-
|
|
14
10
|
var _random = require("../util/random");
|
|
15
|
-
|
|
16
11
|
var _order = require("../order");
|
|
17
|
-
|
|
18
12
|
var _assert = require("assert");
|
|
19
|
-
|
|
20
13
|
var _precedence = require("../precedence");
|
|
21
|
-
|
|
22
14
|
var _template = _interopRequireDefault(require("../templates/template"));
|
|
23
|
-
|
|
24
15
|
var _probability = require("../probability");
|
|
25
|
-
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
function
|
|
29
|
-
|
|
16
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
18
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
19
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
30
20
|
const allowedBinaryOperators = new Set(["+", "-", "*", "/"]);
|
|
31
21
|
const allowedUnaryOperators = new Set(["!", "void", "typeof", "-", "~", "+"]);
|
|
32
|
-
|
|
33
22
|
class Calculator extends _transform.default {
|
|
34
23
|
constructor(o) {
|
|
35
24
|
super(o, _order.ObfuscateOrder.Calculator);
|
|
36
|
-
|
|
37
25
|
_defineProperty(this, "gen", void 0);
|
|
38
|
-
|
|
39
26
|
_defineProperty(this, "ops", void 0);
|
|
40
|
-
|
|
41
27
|
_defineProperty(this, "statesUsed", void 0);
|
|
42
|
-
|
|
43
28
|
_defineProperty(this, "calculatorFn", void 0);
|
|
44
|
-
|
|
45
29
|
_defineProperty(this, "calculatorOpVar", void 0);
|
|
46
|
-
|
|
47
30
|
_defineProperty(this, "calculatorSetOpFn", void 0);
|
|
48
|
-
|
|
49
31
|
this.ops = Object.create(null);
|
|
50
32
|
this.statesUsed = new Set();
|
|
51
33
|
this.calculatorFn = this.getPlaceholder() + "_calc";
|
|
@@ -53,14 +35,11 @@ class Calculator extends _transform.default {
|
|
|
53
35
|
this.calculatorSetOpFn = this.getPlaceholder();
|
|
54
36
|
this.gen = this.getGenerator();
|
|
55
37
|
}
|
|
56
|
-
|
|
57
38
|
apply(tree) {
|
|
58
39
|
super.apply(tree);
|
|
59
|
-
|
|
60
40
|
if (Object.keys(this.ops).length == 0) {
|
|
61
41
|
return;
|
|
62
42
|
}
|
|
63
|
-
|
|
64
43
|
var leftArg = this.getPlaceholder();
|
|
65
44
|
var rightArg = this.getPlaceholder();
|
|
66
45
|
var switchCases = [];
|
|
@@ -68,7 +47,6 @@ class Calculator extends _transform.default {
|
|
|
68
47
|
var [type, operator] = opKey.split("_");
|
|
69
48
|
var code = this.ops[opKey];
|
|
70
49
|
var body = [];
|
|
71
|
-
|
|
72
50
|
if (type === "Binary") {
|
|
73
51
|
body = [(0, _gen.ReturnStatement)((0, _gen.BinaryExpression)(operator, (0, _gen.Identifier)(leftArg), (0, _gen.Identifier)(rightArg)))];
|
|
74
52
|
} else if (type === "Unary") {
|
|
@@ -76,101 +54,87 @@ class Calculator extends _transform.default {
|
|
|
76
54
|
} else {
|
|
77
55
|
throw new Error("Unknown type: " + type);
|
|
78
56
|
}
|
|
79
|
-
|
|
80
57
|
switchCases.push((0, _gen.SwitchCase)((0, _gen.Literal)(code), body));
|
|
81
58
|
});
|
|
82
59
|
var func = (0, _gen.FunctionDeclaration)(this.calculatorFn, [leftArg, rightArg].map(x => (0, _gen.Identifier)(x)), [(0, _gen.SwitchStatement)((0, _gen.Identifier)(this.calculatorOpVar), switchCases)]);
|
|
83
60
|
(0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.calculatorOpVar)));
|
|
84
|
-
(0, _insert.prepend)(tree, (0, _template.default)(
|
|
61
|
+
(0, _insert.prepend)(tree, (0, _template.default)(`function {name}(a){
|
|
62
|
+
a = {b} + ({b}=a, 0);
|
|
63
|
+
return a;
|
|
64
|
+
}`).single({
|
|
85
65
|
name: this.calculatorSetOpFn,
|
|
86
66
|
b: this.calculatorOpVar
|
|
87
67
|
}));
|
|
88
68
|
(0, _insert.prepend)(tree, func);
|
|
89
69
|
}
|
|
90
|
-
|
|
91
70
|
match(object, parents) {
|
|
92
71
|
return object.type === "BinaryExpression" || object.type === "UnaryExpression";
|
|
93
72
|
}
|
|
94
|
-
|
|
95
73
|
transform(object, parents) {
|
|
96
74
|
// Allow percentage
|
|
97
75
|
if (!(0, _probability.ComputeProbabilityMap)(this.options.calculator)) {
|
|
98
76
|
return;
|
|
99
77
|
}
|
|
100
|
-
|
|
101
78
|
var operator = object.operator;
|
|
102
79
|
var type;
|
|
103
|
-
|
|
104
80
|
if (object.type === "BinaryExpression") {
|
|
105
81
|
type = "Binary";
|
|
106
|
-
|
|
107
82
|
if (!allowedBinaryOperators.has(operator)) {
|
|
108
83
|
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
84
|
+
}
|
|
111
85
|
|
|
86
|
+
// Additional checks to ensure complex expressions still work
|
|
112
87
|
var myPrecedence = _precedence.OPERATOR_PRECEDENCE[operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(operator) / 100;
|
|
113
|
-
var precedences = parents.map(x => x.type == "BinaryExpression" && _precedence.OPERATOR_PRECEDENCE[x.operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(x.operator) / 100);
|
|
88
|
+
var precedences = parents.map(x => x.type == "BinaryExpression" && _precedence.OPERATOR_PRECEDENCE[x.operator] + Object.keys(_precedence.OPERATOR_PRECEDENCE).indexOf(x.operator) / 100);
|
|
114
89
|
|
|
90
|
+
// corrupt AST
|
|
115
91
|
if (precedences.find(x => x >= myPrecedence)) {
|
|
116
92
|
return;
|
|
117
93
|
}
|
|
118
|
-
|
|
119
94
|
if (parents.find(x => x.$dispatcherSkip || x.type == "BinaryExpression")) {
|
|
120
95
|
return;
|
|
121
96
|
}
|
|
122
97
|
}
|
|
123
|
-
|
|
124
98
|
if (object.type === "UnaryExpression") {
|
|
125
99
|
type = "Unary";
|
|
126
|
-
|
|
127
100
|
if (!allowedUnaryOperators.has(operator)) {
|
|
128
101
|
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
102
|
+
}
|
|
131
103
|
|
|
104
|
+
// Typeof expression fix
|
|
132
105
|
if (operator === "typeof" && object.argument.type === "Identifier") {
|
|
133
106
|
// `typeof name` is special because it can reference the variable `name` without
|
|
134
107
|
// throwing any errors. If changed, an error could be thrown, breaking the users code
|
|
135
108
|
return;
|
|
136
109
|
}
|
|
137
110
|
}
|
|
138
|
-
|
|
139
111
|
return () => {
|
|
140
112
|
const opKey = type + "_" + operator;
|
|
141
|
-
|
|
142
113
|
if (typeof this.ops[opKey] !== "number") {
|
|
143
114
|
var newState;
|
|
144
|
-
|
|
145
115
|
do {
|
|
146
116
|
newState = (0, _random.getRandomInteger)(-50, 50 + Object.keys(this.ops).length * 5);
|
|
147
117
|
} while (this.statesUsed.has(newState));
|
|
148
|
-
|
|
149
118
|
(0, _assert.ok)(!isNaN(newState));
|
|
150
119
|
this.statesUsed.add(newState);
|
|
151
120
|
this.ops[opKey] = newState;
|
|
152
|
-
|
|
153
121
|
if (type === "Binary") {
|
|
154
|
-
this.log(
|
|
122
|
+
this.log(`left ${operator} right ->`, `${this.calculatorFn}((${newState}, left, right)`);
|
|
155
123
|
} else if (type === "Unary") {
|
|
156
|
-
this.log(
|
|
124
|
+
this.log(`${operator}(argument) ->`, `${this.calculatorFn}(${newState}, argument)`);
|
|
157
125
|
}
|
|
158
|
-
}
|
|
159
|
-
|
|
126
|
+
}
|
|
160
127
|
|
|
128
|
+
// The operator expression sets the operator to be used
|
|
161
129
|
var operatorExpression = (0, _random.choice)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(this.calculatorOpVar), (0, _gen.Literal)(this.ops[opKey])), (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorSetOpFn), [(0, _gen.Literal)(this.ops[opKey])])]);
|
|
162
130
|
var newExpression;
|
|
163
|
-
|
|
164
131
|
if (type === "Binary") {
|
|
165
132
|
newExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorFn), [object.left, object.right, operatorExpression]);
|
|
166
133
|
} else {
|
|
167
134
|
newExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(this.calculatorFn), [object.argument, operatorExpression]);
|
|
168
135
|
}
|
|
169
|
-
|
|
170
136
|
this.replace(object, newExpression);
|
|
171
137
|
};
|
|
172
138
|
}
|
|
173
|
-
|
|
174
139
|
}
|
|
175
|
-
|
|
176
140
|
exports.default = Calculator;
|