node-automator 1.0.5 → 1.2.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/commands/deobfuscate.js +15 -0
- package/commands/mgr.js +4 -0
- package/commands/register_search_install_location.js +12 -0
- package/commands/which.js +8 -49
- package/package.json +7 -2
- package/utils/deobfuscator/deobfuscator.js +97 -0
- package/utils/deobfuscator/helpers/declaration.js +57 -0
- package/utils/deobfuscator/helpers/expression.js +36 -0
- package/utils/deobfuscator/helpers/misc.js +38 -0
- package/utils/deobfuscator/helpers/strings/decoders/base64StringDecoder.js +50 -0
- package/utils/deobfuscator/helpers/strings/decoders/basicStringDecoder.js +28 -0
- package/utils/deobfuscator/helpers/strings/decoders/rc4StringDecoder.js +77 -0
- package/utils/deobfuscator/helpers/strings/decoders/stringDecoder.js +22 -0
- package/utils/deobfuscator/helpers/strings/rotation/rotation.js +216 -0
- package/utils/deobfuscator/helpers/strings/util/util.js +30 -0
- package/utils/deobfuscator/helpers/variable.js +140 -0
- package/utils/deobfuscator/index.js +25 -0
- package/utils/deobfuscator/transformations/config.js +43 -0
- package/utils/deobfuscator/transformations/controlFlow/controlFlowRecoverer.js +160 -0
- package/utils/deobfuscator/transformations/controlFlow/deadBranchRemover.js +120 -0
- package/utils/deobfuscator/transformations/controlFlow/sequenceSplitter.js +168 -0
- package/utils/deobfuscator/transformations/expressions/expressionSimplifier.js +288 -0
- package/utils/deobfuscator/transformations/objects/objectPacker.js +125 -0
- package/utils/deobfuscator/transformations/objects/objectSimplifier.js +71 -0
- package/utils/deobfuscator/transformations/objects/proxyObject.js +144 -0
- package/utils/deobfuscator/transformations/properties/propertySimplifier.js +70 -0
- package/utils/deobfuscator/transformations/proxyFunctions/proxyFunction.js +151 -0
- package/utils/deobfuscator/transformations/proxyFunctions/proxyFunctionInliner.js +46 -0
- package/utils/deobfuscator/transformations/strings/stringRevealer.js +381 -0
- package/utils/deobfuscator/transformations/transformation.js +28 -0
- package/utils/deobfuscator/transformations/variables/constantPropagator.js +73 -0
- package/utils/deobfuscator/transformations/variables/reassignmentRemover.js +78 -0
- package/utils/deobfuscator/transformations/variables/unusedVariableRemover.js +93 -0
- package/utils/log_tool.js +1 -1
- package/utils/reg_tool.js +66 -0
- package/utils/request_tool.js +10 -21
- package/utils/shell_tool.js +2 -1
- package/utils/which_tool.js +54 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.ObjectPacker = void 0;
|
|
30
|
+
const t = __importStar(require("@babel/types"));
|
|
31
|
+
const variable_1 = require("../../helpers/variable");
|
|
32
|
+
const transformation_1 = require("../transformation");
|
|
33
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
34
|
+
class ObjectPacker extends transformation_1.Transformation {
|
|
35
|
+
/**
|
|
36
|
+
* Executes the transformation.
|
|
37
|
+
* @param log The log function.
|
|
38
|
+
*/
|
|
39
|
+
execute(log) {
|
|
40
|
+
const self = this;
|
|
41
|
+
(0, traverse_1.default)(this.ast, {
|
|
42
|
+
enter(path) {
|
|
43
|
+
const variable = (0, variable_1.findConstantVariable)(path, isEmptyObjectExpression);
|
|
44
|
+
if (!variable) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const parentPath = path.getStatementParent();
|
|
48
|
+
if (!parentPath ||
|
|
49
|
+
parentPath.parentPath == undefined ||
|
|
50
|
+
typeof parentPath.key != 'number') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const statements = parentPath.parentPath.node[parentPath.parentKey];
|
|
54
|
+
let numRemoved = 0;
|
|
55
|
+
for (let i = parentPath.key + 1; i < statements.length; i++) {
|
|
56
|
+
const node = statements[i];
|
|
57
|
+
if (t.isExpressionStatement(node) &&
|
|
58
|
+
self.isPropertyAssignment(node.expression, variable.name)) {
|
|
59
|
+
// replace multiple properties assigned in same statement
|
|
60
|
+
if (self.isPropertyAssignment(node.expression.right, variable.name)) {
|
|
61
|
+
const properties = [node.expression.left];
|
|
62
|
+
let right = node.expression.right;
|
|
63
|
+
while (self.isPropertyAssignment(right, variable.name)) {
|
|
64
|
+
properties.push(right.left);
|
|
65
|
+
right = right.right;
|
|
66
|
+
}
|
|
67
|
+
// don't duplicate expressions with side effects
|
|
68
|
+
if (!t.isLiteral(right)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
for (const { property } of properties) {
|
|
72
|
+
const isComputed = !t.isStringLiteral(property) &&
|
|
73
|
+
!t.isNumericLiteral(property) &&
|
|
74
|
+
!t.isIdentifier(property);
|
|
75
|
+
const objectProperty = t.objectProperty(property, right, isComputed);
|
|
76
|
+
variable.expression.properties.push(objectProperty);
|
|
77
|
+
self.setChanged();
|
|
78
|
+
numRemoved++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const key = node.expression.left.property;
|
|
83
|
+
const isComputed = !t.isStringLiteral(key) &&
|
|
84
|
+
!t.isNumericLiteral(key) &&
|
|
85
|
+
!t.isIdentifier(key);
|
|
86
|
+
const property = t.objectProperty(key, node.expression.right, isComputed);
|
|
87
|
+
variable.expression.properties.push(property);
|
|
88
|
+
self.setChanged();
|
|
89
|
+
numRemoved++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
statements.splice(parentPath.key + 1, numRemoved);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return this.hasChanged();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns whether a node is setting a property on a given object.
|
|
103
|
+
* @param node The AST node.
|
|
104
|
+
* @param objectName The name of the object.
|
|
105
|
+
* @returns Whether.
|
|
106
|
+
*/
|
|
107
|
+
isPropertyAssignment(node, objectName) {
|
|
108
|
+
return (t.isAssignmentExpression(node) &&
|
|
109
|
+
t.isMemberExpression(node.left) &&
|
|
110
|
+
t.isIdentifier(node.left.object) &&
|
|
111
|
+
node.left.object.name == objectName);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.ObjectPacker = ObjectPacker;
|
|
115
|
+
ObjectPacker.properties = {
|
|
116
|
+
key: 'objectPacking'
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Returns whether a node is an empty object expression.
|
|
120
|
+
* @param node The node.
|
|
121
|
+
* @returns Whether.
|
|
122
|
+
*/
|
|
123
|
+
const isEmptyObjectExpression = (node) => {
|
|
124
|
+
return t.isObjectExpression(node) && node.properties.length == 0;
|
|
125
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ObjectSimplifier = void 0;
|
|
7
|
+
const transformation_1 = require("../transformation");
|
|
8
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
9
|
+
const variable_1 = require("../../helpers/variable");
|
|
10
|
+
const proxyObject_1 = require("./proxyObject");
|
|
11
|
+
const misc_1 = require("../../helpers/misc");
|
|
12
|
+
class ObjectSimplifier extends transformation_1.Transformation {
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new transformation.
|
|
15
|
+
* @param ast The AST.
|
|
16
|
+
* @param config The config.
|
|
17
|
+
*/
|
|
18
|
+
constructor(ast, config) {
|
|
19
|
+
super(ast, config);
|
|
20
|
+
this.config = config;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Executes the transformation.
|
|
24
|
+
* @param log The log function.
|
|
25
|
+
* @returns Whether any changes were made.
|
|
26
|
+
*/
|
|
27
|
+
execute(log) {
|
|
28
|
+
const self = this;
|
|
29
|
+
const usages = [];
|
|
30
|
+
let depth = 0;
|
|
31
|
+
(0, traverse_1.default)(this.ast, {
|
|
32
|
+
enter(path) {
|
|
33
|
+
(0, misc_1.setProperty)(path, 'depth', depth++);
|
|
34
|
+
const variable = (0, variable_1.findConstantVariable)(path, proxyObject_1.isProxyObjectExpression);
|
|
35
|
+
if (!variable) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// check if object values are modified
|
|
39
|
+
for (const referencePath of variable.binding.referencePaths) {
|
|
40
|
+
if (referencePath.parentPath &&
|
|
41
|
+
referencePath.parentPath.isMemberExpression() &&
|
|
42
|
+
referencePath.parentPath.parentPath &&
|
|
43
|
+
referencePath.parentPath.parentPath.isAssignmentExpression() &&
|
|
44
|
+
referencePath.parentPath.key == 'left') {
|
|
45
|
+
if (!self.config.unsafeReplace) {
|
|
46
|
+
log(`Not replacing object ${variable.name} as it is modified`);
|
|
47
|
+
path.skip();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const proxyObject = new proxyObject_1.ProxyObject(variable);
|
|
53
|
+
proxyObject.process();
|
|
54
|
+
usages.push(...proxyObject.getUsages().map(p => [p, proxyObject]));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
// replace innermost usages first
|
|
58
|
+
usages.sort((a, b) => (0, misc_1.getProperty)(b[0], 'depth') - (0, misc_1.getProperty)(a[0], 'depth'));
|
|
59
|
+
for (const [path, proxyObject] of usages) {
|
|
60
|
+
if (proxyObject.replaceUsage(path)) {
|
|
61
|
+
this.setChanged();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return this.hasChanged();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.ObjectSimplifier = ObjectSimplifier;
|
|
68
|
+
ObjectSimplifier.properties = {
|
|
69
|
+
key: 'objectSimplification',
|
|
70
|
+
rebuildScopeTree: true
|
|
71
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.ProxyObject = exports.isProxyObjectExpression = void 0;
|
|
27
|
+
const t = __importStar(require("@babel/types"));
|
|
28
|
+
const misc_1 = require("../../helpers/misc");
|
|
29
|
+
const proxyFunction_1 = require("../proxyFunctions/proxyFunction");
|
|
30
|
+
/**
|
|
31
|
+
* Returns whether a node is a proxy object.
|
|
32
|
+
* @param node The node.
|
|
33
|
+
* @returns Whether.
|
|
34
|
+
*/
|
|
35
|
+
const isProxyObjectExpression = (node) => {
|
|
36
|
+
return t.isObjectExpression(node) && node.properties.length > 0;
|
|
37
|
+
};
|
|
38
|
+
exports.isProxyObjectExpression = isProxyObjectExpression;
|
|
39
|
+
class ProxyObject {
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new proxy object.
|
|
42
|
+
* @param variable The variable.
|
|
43
|
+
*/
|
|
44
|
+
constructor(variable) {
|
|
45
|
+
this.literalProperties = new Map();
|
|
46
|
+
this.proxyFunctionProperties = new Map();
|
|
47
|
+
this.variable = variable;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Finds all the object's entries which can be replaced.
|
|
51
|
+
*/
|
|
52
|
+
process() {
|
|
53
|
+
for (const property of this.variable.expression.properties) {
|
|
54
|
+
if (t.isObjectProperty(property) && this.isLiteralPropertyKey(property)) {
|
|
55
|
+
const key = t.isIdentifier(property.key) ? property.key.name : property.key.value;
|
|
56
|
+
if (t.isLiteral(property.value)) {
|
|
57
|
+
this.literalProperties.set(key, property.value);
|
|
58
|
+
}
|
|
59
|
+
else if ((0, proxyFunction_1.isProxyFunctionExpression)(property.value)) {
|
|
60
|
+
const proxyFunction = new proxyFunction_1.ProxyFunction(property.value);
|
|
61
|
+
this.proxyFunctionProperties.set(key, proxyFunction);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (t.isObjectMethod(property) && this.isLiteralMethodKey(property)) {
|
|
65
|
+
const key = t.isIdentifier(property.key) ? property.key.name : property.key.value;
|
|
66
|
+
if ((0, proxyFunction_1.isProxyFunctionExpression)(property)) {
|
|
67
|
+
const proxyFunction = new proxyFunction_1.ProxyFunction(property);
|
|
68
|
+
this.proxyFunctionProperties.set(key, proxyFunction);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns the usages of the object.
|
|
75
|
+
* @returns The usages.
|
|
76
|
+
*/
|
|
77
|
+
getUsages() {
|
|
78
|
+
return this.variable.binding.referencePaths;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Attempts to replace a usage of the object.
|
|
82
|
+
* @param path The path of the usage.
|
|
83
|
+
* @returns Whether it was replaced.
|
|
84
|
+
*/
|
|
85
|
+
replaceUsage(path) {
|
|
86
|
+
const parentPath = path.parentPath;
|
|
87
|
+
if (parentPath &&
|
|
88
|
+
parentPath.isMemberExpression() &&
|
|
89
|
+
this.isLiteralMemberKey(parentPath.node) &&
|
|
90
|
+
(!parentPath.parentPath ||
|
|
91
|
+
!parentPath.parentPath.isAssignmentExpression() ||
|
|
92
|
+
parentPath.parentKey != 'left')) {
|
|
93
|
+
const key = t.isIdentifier(parentPath.node.property)
|
|
94
|
+
? parentPath.node.property.name
|
|
95
|
+
: parentPath.node.property.value;
|
|
96
|
+
if (this.literalProperties.has(key)) {
|
|
97
|
+
const value = this.literalProperties.get(key);
|
|
98
|
+
parentPath.replaceWith((0, misc_1.copyExpression)(value));
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
else if (parentPath.parentPath &&
|
|
102
|
+
parentPath.parentPath.isCallExpression() &&
|
|
103
|
+
parentPath.key == 'callee' &&
|
|
104
|
+
this.proxyFunctionProperties.has(key)) {
|
|
105
|
+
const proxyFunction = this.proxyFunctionProperties.get(key);
|
|
106
|
+
const replacement = proxyFunction.getReplacement(parentPath.parentPath.node.arguments);
|
|
107
|
+
parentPath.parentPath.replaceWith(replacement);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Returns whether an object property has a literal key.
|
|
115
|
+
* @param property The object property.
|
|
116
|
+
* @returns Whether.
|
|
117
|
+
*/
|
|
118
|
+
isLiteralPropertyKey(property) {
|
|
119
|
+
return (t.isStringLiteral(property.key) ||
|
|
120
|
+
t.isNumericLiteral(property.key) ||
|
|
121
|
+
(!property.computed && t.isIdentifier(property.key)));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Returns whether an object method has a literal key.
|
|
125
|
+
* @param property The object method.
|
|
126
|
+
* @returns Whether.
|
|
127
|
+
*/
|
|
128
|
+
isLiteralMethodKey(property) {
|
|
129
|
+
return (t.isStringLiteral(property.key) ||
|
|
130
|
+
t.isNumericLiteral(property.key) ||
|
|
131
|
+
(!property.computed && t.isIdentifier(property.key)));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Returns whether a member expression has a literal key.
|
|
135
|
+
* @param member The member expression.
|
|
136
|
+
* @returns Whether.
|
|
137
|
+
*/
|
|
138
|
+
isLiteralMemberKey(member) {
|
|
139
|
+
return (t.isStringLiteral(member.property) ||
|
|
140
|
+
t.isNumericLiteral(member.property) ||
|
|
141
|
+
(!member.computed && t.isIdentifier(member.property)));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.ProxyObject = ProxyObject;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.PropertySimplifier = void 0;
|
|
30
|
+
const t = __importStar(require("@babel/types"));
|
|
31
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
32
|
+
const transformation_1 = require("../transformation");
|
|
33
|
+
class PropertySimplifier extends transformation_1.Transformation {
|
|
34
|
+
/**
|
|
35
|
+
* Executes the transformation.
|
|
36
|
+
* @param log The log function.
|
|
37
|
+
*/
|
|
38
|
+
execute(log) {
|
|
39
|
+
const self = this;
|
|
40
|
+
(0, traverse_1.default)(this.ast, {
|
|
41
|
+
MemberExpression(path) {
|
|
42
|
+
if (path.node.computed &&
|
|
43
|
+
t.isStringLiteral(path.node.property) &&
|
|
44
|
+
t.isValidIdentifier(path.node.property.value)) {
|
|
45
|
+
path.node.property = t.identifier(path.node.property.value);
|
|
46
|
+
path.node.computed = false;
|
|
47
|
+
self.setChanged();
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
ObjectProperty(path) {
|
|
51
|
+
if (path.node.computed &&
|
|
52
|
+
t.isStringLiteral(path.node.key) &&
|
|
53
|
+
t.isValidIdentifier(path.node.key.value)) {
|
|
54
|
+
path.node.key = t.identifier(path.node.key.value);
|
|
55
|
+
path.node.computed = false;
|
|
56
|
+
self.setChanged();
|
|
57
|
+
}
|
|
58
|
+
else if (path.node.computed &&
|
|
59
|
+
(t.isStringLiteral(path.node.key) || t.isNumericLiteral(path.node.key))) {
|
|
60
|
+
path.node.computed = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return this.hasChanged();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.PropertySimplifier = PropertySimplifier;
|
|
68
|
+
PropertySimplifier.properties = {
|
|
69
|
+
key: 'propertySimplification'
|
|
70
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.ProxyFunctionVariable = exports.ProxyFunction = exports.isProxyFunctionExpression = void 0;
|
|
30
|
+
const t = __importStar(require("@babel/types"));
|
|
31
|
+
const misc_1 = require("../../helpers/misc");
|
|
32
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
33
|
+
/**
|
|
34
|
+
* Returns whether a proxy function expression.
|
|
35
|
+
* @param node The node.
|
|
36
|
+
* @returns Whether.
|
|
37
|
+
*/
|
|
38
|
+
const isProxyFunctionExpression = (node) => {
|
|
39
|
+
return (t.isFunction(node) &&
|
|
40
|
+
node.params.every(p => t.isIdentifier(p)) &&
|
|
41
|
+
((t.isBlockStatement(node.body) &&
|
|
42
|
+
node.body.body.length == 1 &&
|
|
43
|
+
t.isReturnStatement(node.body.body[0]) &&
|
|
44
|
+
(node.body.body[0].argument == undefined ||
|
|
45
|
+
(t.isExpression(node.body.body[0].argument) &&
|
|
46
|
+
isProxyValue(node.body.body[0].argument)))) ||
|
|
47
|
+
(t.isArrowFunctionExpression(node) &&
|
|
48
|
+
t.isExpression(node.body) &&
|
|
49
|
+
isProxyValue(node.body))));
|
|
50
|
+
};
|
|
51
|
+
exports.isProxyFunctionExpression = isProxyFunctionExpression;
|
|
52
|
+
/**
|
|
53
|
+
* Returns whether a node is a valid proxy function return value.
|
|
54
|
+
* @param node The node.
|
|
55
|
+
* @returns Whether.
|
|
56
|
+
*/
|
|
57
|
+
const isProxyValue = (node) => {
|
|
58
|
+
if (t.isFunction(node) || t.isBlockStatement(node) || t.isSequenceExpression(node)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
let isValid = true;
|
|
62
|
+
(0, traverse_1.default)(node, {
|
|
63
|
+
['SequenceExpression|BlockStatement|Function'](path) {
|
|
64
|
+
isValid = false;
|
|
65
|
+
path.stop();
|
|
66
|
+
},
|
|
67
|
+
noScope: true
|
|
68
|
+
});
|
|
69
|
+
return isValid;
|
|
70
|
+
};
|
|
71
|
+
class ProxyFunction {
|
|
72
|
+
/**
|
|
73
|
+
* Creates a new proxy function.
|
|
74
|
+
* @param expression The proxy function expression.
|
|
75
|
+
*/
|
|
76
|
+
constructor(expression) {
|
|
77
|
+
this.expression = expression;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns the replacement for a call of the proxy function.
|
|
81
|
+
* @param args The arguments of the call.
|
|
82
|
+
* @returns The replacement expression.
|
|
83
|
+
*/
|
|
84
|
+
getReplacement(args) {
|
|
85
|
+
const expression = t.isExpression(this.expression.body)
|
|
86
|
+
? (0, misc_1.copyExpression)(this.expression.body)
|
|
87
|
+
: this.expression.body.body[0].argument
|
|
88
|
+
? (0, misc_1.copyExpression)(this.expression.body.body[0].argument)
|
|
89
|
+
: t.identifier('undefined');
|
|
90
|
+
this.replaceParameters(expression, args);
|
|
91
|
+
return expression;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Replaces usages of the proxy function's parameters with the concrete arguments for a given call.
|
|
95
|
+
* @param expression The expression.
|
|
96
|
+
* @param args The arguments of the call.
|
|
97
|
+
*/
|
|
98
|
+
replaceParameters(expression, args) {
|
|
99
|
+
const paramMap = new Map(this.expression.params.map((param, index) => [
|
|
100
|
+
param.name,
|
|
101
|
+
args[index] || t.identifier('undefined')
|
|
102
|
+
]));
|
|
103
|
+
const pathsToReplace = [];
|
|
104
|
+
(0, traverse_1.default)(expression, {
|
|
105
|
+
enter(path) {
|
|
106
|
+
if (t.isIdentifier(path.node) && paramMap.has(path.node.name)) {
|
|
107
|
+
const replacement = paramMap.get(path.node.name);
|
|
108
|
+
pathsToReplace.push([path, replacement]);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
noScope: true
|
|
112
|
+
});
|
|
113
|
+
for (const [path, replacement] of pathsToReplace) {
|
|
114
|
+
path.replaceWith(replacement);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.ProxyFunction = ProxyFunction;
|
|
119
|
+
class ProxyFunctionVariable extends ProxyFunction {
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new proxy function variable.
|
|
122
|
+
* @param variable The variable.
|
|
123
|
+
*/
|
|
124
|
+
constructor(variable) {
|
|
125
|
+
super(variable.expression);
|
|
126
|
+
this.variable = variable;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Returns the calls to the proxy function.
|
|
130
|
+
* @returns The calls to the proxy function.
|
|
131
|
+
*/
|
|
132
|
+
getCalls() {
|
|
133
|
+
return this.variable.binding.referencePaths;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Attempts to replace a call of the proxy function.
|
|
137
|
+
* @param path The path of the call.
|
|
138
|
+
* @returns Whether it was replaced.
|
|
139
|
+
*/
|
|
140
|
+
replaceCall(path) {
|
|
141
|
+
if (path.parentPath && path.parentPath.isCallExpression() && path.key == 'callee') {
|
|
142
|
+
const expression = this.getReplacement(path.parentPath.node.arguments);
|
|
143
|
+
path.parentPath.replaceWith(expression);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.ProxyFunctionVariable = ProxyFunctionVariable;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ProxyFunctionInliner = void 0;
|
|
7
|
+
const transformation_1 = require("../transformation");
|
|
8
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
9
|
+
const variable_1 = require("../../helpers/variable");
|
|
10
|
+
const proxyFunction_1 = require("./proxyFunction");
|
|
11
|
+
const misc_1 = require("../../helpers/misc");
|
|
12
|
+
class ProxyFunctionInliner extends transformation_1.Transformation {
|
|
13
|
+
/**
|
|
14
|
+
* Executes the transformation.
|
|
15
|
+
* @param log The log function.
|
|
16
|
+
* @returns Whether any changes were made.
|
|
17
|
+
*/
|
|
18
|
+
execute(log) {
|
|
19
|
+
const usages = [];
|
|
20
|
+
let depth = 0;
|
|
21
|
+
(0, traverse_1.default)(this.ast, {
|
|
22
|
+
enter(path) {
|
|
23
|
+
(0, misc_1.setProperty)(path, 'depth', depth++);
|
|
24
|
+
const variable = (0, variable_1.findConstantVariable)(path, proxyFunction_1.isProxyFunctionExpression, true);
|
|
25
|
+
if (!variable) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const proxyFunction = new proxyFunction_1.ProxyFunctionVariable(variable);
|
|
29
|
+
usages.push(...proxyFunction.getCalls().map(p => [p, proxyFunction]));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
// replace innermost proxy calls first
|
|
33
|
+
usages.sort((a, b) => (0, misc_1.getProperty)(b[0], 'depth') - (0, misc_1.getProperty)(a[0], 'depth'));
|
|
34
|
+
for (const [path, proxyFunction] of usages) {
|
|
35
|
+
if (proxyFunction.replaceCall(path)) {
|
|
36
|
+
this.setChanged();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return this.hasChanged();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.ProxyFunctionInliner = ProxyFunctionInliner;
|
|
43
|
+
ProxyFunctionInliner.properties = {
|
|
44
|
+
key: 'proxyFunctionInlining',
|
|
45
|
+
rebuildScopeTree: true
|
|
46
|
+
};
|