js-confuser 1.6.0 → 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/CHANGELOG.md +23 -0
- package/README.md +215 -170
- package/dist/constants.js +6 -2
- package/dist/obfuscator.js +0 -6
- package/dist/options.js +4 -4
- package/dist/presets.js +6 -7
- package/dist/templates/crash.js +2 -2
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/dispatcher.js +4 -1
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +89 -58
- package/dist/transforms/flatten.js +224 -147
- package/dist/transforms/identifier/movedDeclarations.js +38 -85
- package/dist/transforms/identifier/renameVariables.js +94 -41
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +2 -2
- package/dist/transforms/rgf.js +139 -246
- package/dist/transforms/stack.js +42 -1
- package/dist/transforms/transform.js +1 -1
- package/dist/util/gen.js +2 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +24 -3
- 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 +1 -1
- package/src/constants.ts +3 -0
- package/src/obfuscator.ts +0 -4
- package/src/options.ts +9 -86
- package/src/presets.ts +6 -7
- package/src/templates/crash.ts +10 -10
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/dispatcher.ts +5 -1
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +130 -129
- package/src/transforms/flatten.ts +357 -290
- package/src/transforms/identifier/movedDeclarations.ts +50 -96
- package/src/transforms/identifier/renameVariables.ts +120 -56
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +11 -2
- package/src/transforms/rgf.ts +214 -404
- package/src/transforms/stack.ts +62 -0
- package/src/transforms/transform.ts +6 -2
- package/src/util/gen.ts +7 -2
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +26 -2
- package/test/code/ES6.src.js +24 -0
- package/test/transforms/flatten.test.ts +352 -88
- package/test/transforms/identifier/movedDeclarations.test.ts +37 -9
- package/test/transforms/identifier/renameVariables.test.ts +37 -0
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +19 -0
- package/test/transforms/rgf.test.ts +262 -353
- package/test/transforms/stack.test.ts +52 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
|
@@ -11,7 +11,7 @@ var _constants = require("../constants");
|
|
|
11
11
|
|
|
12
12
|
var _order = require("../order");
|
|
13
13
|
|
|
14
|
-
var _traverse =
|
|
14
|
+
var _traverse = require("../traverse");
|
|
15
15
|
|
|
16
16
|
var _gen = require("../util/gen");
|
|
17
17
|
|
|
@@ -23,71 +23,87 @@ var _random = require("../util/random");
|
|
|
23
23
|
|
|
24
24
|
var _transform = _interopRequireDefault(require("./transform"));
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
26
|
+
var _functionLength = require("../templates/functionLength");
|
|
29
27
|
|
|
30
|
-
function
|
|
28
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
29
|
|
|
32
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; }
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
|
-
*
|
|
33
|
+
* Flatten takes functions and isolates them from their original scope, and brings it to the top level of the program.
|
|
36
34
|
*
|
|
37
|
-
*
|
|
35
|
+
* An additional `flatObject` parameter is passed in, giving access to the original scoped variables.
|
|
36
|
+
*
|
|
37
|
+
* The `flatObject` uses `get` and `set` properties to allow easy an AST transformation:
|
|
38
38
|
*
|
|
39
39
|
* ```js
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* // Input
|
|
41
|
+
* function myFunction(myParam){
|
|
42
|
+
* modified = true;
|
|
43
|
+
* if(reference) {
|
|
44
|
+
*
|
|
45
|
+
* }
|
|
46
|
+
* ...
|
|
47
|
+
* console.log(myParam);
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* // Output
|
|
51
|
+
* function myFunction_flat([myParam], flatObject){
|
|
52
|
+
* flatObject["set_modified"] = true;
|
|
53
|
+
* if(flatObject["get_reference"]) {
|
|
54
|
+
*
|
|
55
|
+
* }
|
|
56
|
+
* ...
|
|
57
|
+
* console.log(myParam)
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* function myFunction(){
|
|
61
|
+
* var flatObject = {
|
|
62
|
+
* set set_modified(v) { modified = v }
|
|
63
|
+
* get get_reference() { return reference }
|
|
64
|
+
* }
|
|
65
|
+
* return myFunction_flat([...arguments], flatObject)
|
|
42
66
|
* }
|
|
43
67
|
* ```
|
|
44
68
|
*
|
|
45
69
|
* Flatten is used to make functions eligible for the RGF transformation.
|
|
70
|
+
*
|
|
71
|
+
* - `myFunction_flat` is now eligible because it does not rely on outside scoped variables
|
|
46
72
|
*/
|
|
47
73
|
class Flatten extends _transform.default {
|
|
74
|
+
// Array of FunctionDeclaration nodes
|
|
48
75
|
constructor(o) {
|
|
49
76
|
super(o, _order.ObfuscateOrder.Flatten);
|
|
50
77
|
|
|
78
|
+
_defineProperty(this, "isDebug", false);
|
|
79
|
+
|
|
51
80
|
_defineProperty(this, "definedNames", void 0);
|
|
52
81
|
|
|
53
82
|
_defineProperty(this, "flattenedFns", void 0);
|
|
54
83
|
|
|
55
84
|
_defineProperty(this, "gen", void 0);
|
|
56
85
|
|
|
86
|
+
_defineProperty(this, "functionLengthName", void 0);
|
|
87
|
+
|
|
57
88
|
this.definedNames = new Map();
|
|
58
89
|
this.flattenedFns = [];
|
|
59
|
-
this.gen = this.getGenerator();
|
|
90
|
+
this.gen = this.getGenerator("mangled");
|
|
91
|
+
|
|
92
|
+
if (this.isDebug) {
|
|
93
|
+
console.warn("Flatten debug mode");
|
|
94
|
+
}
|
|
60
95
|
}
|
|
61
96
|
|
|
62
97
|
apply(tree) {
|
|
63
|
-
(0, _traverse.default)(tree, (o, p) => {
|
|
64
|
-
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {
|
|
65
|
-
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
66
|
-
|
|
67
|
-
if (info.spec.isReferenced) {
|
|
68
|
-
if (info.spec.isDefined) {
|
|
69
|
-
var c = (0, _insert.getVarContext)(o, p);
|
|
70
|
-
|
|
71
|
-
if (c) {
|
|
72
|
-
if (!this.definedNames.has(c)) {
|
|
73
|
-
this.definedNames.set(c, new Set([o.name]));
|
|
74
|
-
} else {
|
|
75
|
-
this.definedNames.get(c).add(o.name);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
98
|
super.apply(tree);
|
|
83
99
|
|
|
84
100
|
if (this.flattenedFns.length) {
|
|
85
|
-
(0, _insert.prepend)(tree,
|
|
101
|
+
(0, _insert.prepend)(tree, ...this.flattenedFns);
|
|
86
102
|
}
|
|
87
103
|
}
|
|
88
104
|
|
|
89
105
|
match(object, parents) {
|
|
90
|
-
return (object.type == "FunctionDeclaration" || object.type === "FunctionExpression") && object.body.type == "BlockStatement" && !object.generator && !object.params.find(x => x.type !== "Identifier");
|
|
106
|
+
return (object.type == "FunctionDeclaration" || object.type === "FunctionExpression") && object.body.type == "BlockStatement" && !object.$requiresEval && !object.generator && !object.params.find(x => x.type !== "Identifier");
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
transform(object, parents) {
|
|
@@ -101,7 +117,7 @@ class Flatten extends _transform.default {
|
|
|
101
117
|
} // Don't change getter/setter methods
|
|
102
118
|
|
|
103
119
|
|
|
104
|
-
if (parents[0].type === "Property" && parents[0].value === object && parents[0].kind !== "init") {
|
|
120
|
+
if (parents[0].type === "Property" && parents[0].value === object && (parents[0].kind !== "init" || parents[0].method)) {
|
|
105
121
|
return;
|
|
106
122
|
}
|
|
107
123
|
}
|
|
@@ -111,76 +127,54 @@ class Flatten extends _transform.default {
|
|
|
111
127
|
var currentFnName = object.type === "FunctionDeclaration" ? (_object$id = object.id) === null || _object$id === void 0 ? void 0 : _object$id.name : ((_parents$ = parents[0]) === null || _parents$ === void 0 ? void 0 : _parents$.type) === "VariableDeclarator" && ((_parents$0$id = parents[0].id) === null || _parents$0$id === void 0 ? void 0 : _parents$0$id.type) === "Identifier" && ((_parents$0$id2 = parents[0].id) === null || _parents$0$id2 === void 0 ? void 0 : _parents$0$id2.name);
|
|
112
128
|
|
|
113
129
|
if (((_parents$2 = parents[0]) === null || _parents$2 === void 0 ? void 0 : _parents$2.type) === "Property" && (_parents$3 = parents[0]) !== null && _parents$3 !== void 0 && _parents$3.key) {
|
|
114
|
-
var _parents$4, _parents$4$key
|
|
130
|
+
var _parents$4, _parents$4$key;
|
|
115
131
|
|
|
116
|
-
currentFnName = currentFnName || String((
|
|
132
|
+
currentFnName = currentFnName || String((_parents$4 = parents[0]) === null || _parents$4 === void 0 ? void 0 : (_parents$4$key = _parents$4.key) === null || _parents$4$key === void 0 ? void 0 : _parents$4$key.name);
|
|
117
133
|
}
|
|
118
134
|
|
|
119
135
|
if (!currentFnName) currentFnName = "unnamed";
|
|
120
|
-
var
|
|
121
|
-
var references = new Set();
|
|
122
|
-
var modified = new Set();
|
|
136
|
+
var definedMap = new Map();
|
|
123
137
|
var illegal = new Set();
|
|
124
138
|
var isIllegal = false;
|
|
125
|
-
var
|
|
126
|
-
parents.forEach(x => {
|
|
127
|
-
var set = this.definedNames.get(x);
|
|
128
|
-
|
|
129
|
-
if (set) {
|
|
130
|
-
set.forEach(name => definedAbove.add(name));
|
|
131
|
-
}
|
|
132
|
-
});
|
|
139
|
+
var identifierNodes = [];
|
|
133
140
|
(0, _traverse.walk)(object, parents, (o, p) => {
|
|
134
|
-
if (
|
|
135
|
-
|
|
141
|
+
if (o.type === "Identifier" && o.name === "arguments" || o.type === "UnaryExpression" && o.operator === "delete" || o.type == "ThisExpression" || o.type == "Super" || o.type == "MetaProperty") {
|
|
142
|
+
isIllegal = true;
|
|
143
|
+
return "EXIT";
|
|
136
144
|
}
|
|
137
145
|
|
|
138
|
-
if (o.type == "Identifier" && !this.options.globalVariables.has(o.name) && !_constants.reservedIdentifiers.has(o.name)) {
|
|
146
|
+
if (o.type == "Identifier" && o !== object.id && !this.options.globalVariables.has(o.name) && !_constants.reservedIdentifiers.has(o.name)) {
|
|
139
147
|
var info = (0, _identifiers.getIdentifierInfo)(o, p);
|
|
140
148
|
|
|
141
149
|
if (!info.spec.isReferenced) {
|
|
142
150
|
return;
|
|
143
151
|
}
|
|
144
152
|
|
|
145
|
-
if (o.
|
|
153
|
+
if (info.spec.isExported || o.name.startsWith(_constants.noRenameVariablePrefix)) {
|
|
146
154
|
illegal.add(o.name);
|
|
147
|
-
|
|
148
|
-
defined.add(o.name);
|
|
149
|
-
} else if (info.spec.isModified) {
|
|
150
|
-
modified.add(o.name);
|
|
151
|
-
} else {
|
|
152
|
-
references.add(o.name);
|
|
155
|
+
return;
|
|
153
156
|
}
|
|
154
|
-
}
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return "EXIT";
|
|
159
|
-
}
|
|
158
|
+
if (info.spec.isDefined) {
|
|
159
|
+
var definingContext = (0, _insert.getDefiningContext)(o, p);
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
161
|
+
if (!definedMap.has(definingContext)) {
|
|
162
|
+
definedMap.set(definingContext, new Set([o.name]));
|
|
163
|
+
} else {
|
|
164
|
+
definedMap.get(definingContext).add(o.name);
|
|
165
|
+
}
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return "EXIT";
|
|
171
|
-
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
172
169
|
|
|
173
|
-
|
|
174
|
-
isIllegal = true;
|
|
175
|
-
return "EXIT";
|
|
176
|
-
}
|
|
170
|
+
var isDefined = p.find(x => definedMap.has(x) && definedMap.get(x).has(o.name));
|
|
177
171
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
172
|
+
if (!isDefined) {
|
|
173
|
+
identifierNodes.push([o, p, info]);
|
|
174
|
+
}
|
|
181
175
|
}
|
|
182
176
|
|
|
183
|
-
if (o.type == "
|
|
177
|
+
if (o.type == "TryStatement") {
|
|
184
178
|
isIllegal = true;
|
|
185
179
|
return "EXIT";
|
|
186
180
|
}
|
|
@@ -194,86 +188,169 @@ class Flatten extends _transform.default {
|
|
|
194
188
|
return;
|
|
195
189
|
}
|
|
196
190
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
modified.delete(name);
|
|
200
|
-
}); // console.log(object.id.name, illegal, references);
|
|
191
|
+
var newFnName = this.getPlaceholder() + "_flat_" + currentFnName;
|
|
192
|
+
var flatObjectName = this.getPlaceholder() + "_flat_object";
|
|
201
193
|
|
|
202
|
-
|
|
194
|
+
const getFlatObjectMember = propertyName => {
|
|
195
|
+
return (0, _gen.MemberExpression)((0, _gen.Identifier)(flatObjectName), (0, _gen.Literal)(propertyName), true);
|
|
196
|
+
};
|
|
203
197
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
198
|
+
var getterPropNames = Object.create(null);
|
|
199
|
+
var setterPropNames = Object.create(null);
|
|
200
|
+
var typeofPropNames = Object.create(null);
|
|
201
|
+
var callPropNames = Object.create(null);
|
|
207
202
|
|
|
208
|
-
var
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
|
|
203
|
+
for (var [o, p, info] of identifierNodes) {
|
|
204
|
+
var identifierName = o.name;
|
|
205
|
+
if (p.find(x => definedMap.has(x) && definedMap.get(x).has(identifierName))) continue;
|
|
206
|
+
(0, _assert.ok)(!info.spec.isDefined);
|
|
207
|
+
var type = info.spec.isModified ? "setter" : "getter";
|
|
208
|
+
|
|
209
|
+
switch (type) {
|
|
210
|
+
case "setter":
|
|
211
|
+
var setterPropName = setterPropNames[identifierName];
|
|
212
|
+
|
|
213
|
+
if (typeof setterPropName === "undefined") {
|
|
214
|
+
// No getter function made yet, make it (Try to re-use getter name if available)
|
|
215
|
+
setterPropName = getterPropNames[identifierName] || (this.isDebug ? "set_" + identifierName : this.gen.generate());
|
|
216
|
+
setterPropNames[identifierName] = setterPropName;
|
|
217
|
+
} // If an update expression, ensure a getter function is also available. Ex: a++
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if (p[0].type === "UpdateExpression") {
|
|
221
|
+
getterPropNames[identifierName] = setterPropName;
|
|
222
|
+
} else {
|
|
223
|
+
// If assignment on member expression, ensure a getter function is also available: Ex. myObject.property = ...
|
|
224
|
+
var assignmentIndex = p.findIndex(x => x.type === "AssignmentExpression");
|
|
225
|
+
|
|
226
|
+
if (assignmentIndex !== -1 && p[assignmentIndex].left.type !== "Identifier") {
|
|
227
|
+
getterPropNames[identifierName] = setterPropName;
|
|
228
|
+
}
|
|
229
|
+
} // calls flatObject.set_identifier_value(newValue)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
this.replace(o, getFlatObjectMember(setterPropName));
|
|
233
|
+
break;
|
|
234
|
+
|
|
235
|
+
case "getter":
|
|
236
|
+
var getterPropName = getterPropNames[identifierName];
|
|
237
|
+
|
|
238
|
+
if (typeof getterPropName === "undefined") {
|
|
239
|
+
// No getter function made yet, make it (Try to re-use setter name if available)
|
|
240
|
+
getterPropName = setterPropNames[identifierName] || (this.isDebug ? "get_" + identifierName : this.gen.generate());
|
|
241
|
+
getterPropNames[identifierName] = getterPropName;
|
|
242
|
+
} // Typeof expression check
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
if (p[0].type === "UnaryExpression" && p[0].operator === "typeof" && p[0].argument === o) {
|
|
246
|
+
var typeofPropName = typeofPropNames[identifierName];
|
|
247
|
+
|
|
248
|
+
if (typeof typeofPropName === "undefined") {
|
|
249
|
+
// No typeof getter function made yet, make it (Don't re-use getter/setter names)
|
|
250
|
+
typeofPropName = this.isDebug ? "get_typeof_" + identifierName : this.gen.generate();
|
|
251
|
+
typeofPropNames[identifierName] = typeofPropName;
|
|
252
|
+
} // Replace the entire unary expression not just the identifier node
|
|
253
|
+
// calls flatObject.get_typeof_identifier()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
this.replace(p[0], getFlatObjectMember(typeofPropName));
|
|
257
|
+
break;
|
|
258
|
+
} // Bound call-expression check
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
if (p[0].type === "CallExpression" && p[0].callee === o) {
|
|
262
|
+
var callPropName = callPropNames[identifierName];
|
|
231
263
|
|
|
232
|
-
|
|
233
|
-
|
|
264
|
+
if (typeof callPropName === "undefined") {
|
|
265
|
+
callPropName = this.isDebug ? "call_" + identifierName : this.gen.generate();
|
|
266
|
+
callPropNames[identifierName] = callPropName;
|
|
267
|
+
} // Replace the entire call expression not just the identifier node
|
|
268
|
+
// calls flatObject.call_identifier(...arguments)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
this.replace(p[0], (0, _gen.CallExpression)(getFlatObjectMember(callPropName), p[0].arguments));
|
|
272
|
+
break;
|
|
273
|
+
} // calls flatObject.get_identifier_value()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
this.replace(o, getFlatObjectMember(getterPropName));
|
|
277
|
+
break;
|
|
234
278
|
}
|
|
235
|
-
}
|
|
279
|
+
} // Create the getter and setter functions
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
var flatObjectProperties = []; // Getter functions
|
|
283
|
+
|
|
284
|
+
for (var identifierName in getterPropNames) {
|
|
285
|
+
var getterPropName = getterPropNames[identifierName];
|
|
286
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(getterPropName), (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.Identifier)(identifierName))]), true, "get"));
|
|
287
|
+
} // Get typeof functions
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
for (var identifierName in typeofPropNames) {
|
|
291
|
+
var typeofPropName = typeofPropNames[identifierName];
|
|
292
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(typeofPropName), (0, _gen.FunctionExpression)([], [(0, _gen.ReturnStatement)((0, _gen.UnaryExpression)("typeof", (0, _gen.Identifier)(identifierName)))]), true, "get"));
|
|
293
|
+
} // Call functions
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
for (var identifierName in callPropNames) {
|
|
297
|
+
var callPropName = callPropNames[identifierName];
|
|
298
|
+
var argumentsName = this.getPlaceholder();
|
|
299
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(callPropName), (0, _gen.FunctionExpression)([(0, _gen.RestElement)((0, _gen.Identifier)(argumentsName))], [(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(identifierName), [(0, _gen.SpreadElement)((0, _gen.Identifier)(argumentsName))]))]), true));
|
|
300
|
+
} // Setter functions
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
for (var identifierName in setterPropNames) {
|
|
304
|
+
var setterPropName = setterPropNames[identifierName];
|
|
305
|
+
var newValueParameterName = this.getPlaceholder();
|
|
306
|
+
flatObjectProperties.push((0, _gen.Property)((0, _gen.Literal)(setterPropName), (0, _gen.FunctionExpression)([(0, _gen.Identifier)(newValueParameterName)], [(0, _gen.ExpressionStatement)((0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(identifierName), (0, _gen.Identifier)(newValueParameterName)))]), true, "set"));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (!this.isDebug) {
|
|
310
|
+
(0, _random.shuffle)(flatObjectProperties);
|
|
311
|
+
}
|
|
312
|
+
|
|
236
313
|
var newBody = (0, _insert.getBlockBody)(object.body); // Remove 'use strict' directive
|
|
237
314
|
|
|
238
315
|
if (newBody.length > 0 && newBody[0].directive) {
|
|
239
316
|
newBody.shift();
|
|
240
317
|
}
|
|
241
318
|
|
|
242
|
-
var
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
this.flattenedFns.push(
|
|
246
|
-
var
|
|
247
|
-
|
|
248
|
-
var
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
319
|
+
var newFunctionDeclaration = (0, _gen.FunctionDeclaration)(newFnName, [(0, _gen.ArrayPattern)((0, _insert.clone)(object.params)), (0, _gen.Identifier)(flatObjectName)], newBody);
|
|
320
|
+
newFunctionDeclaration.async = !!object.async;
|
|
321
|
+
newFunctionDeclaration.generator = false;
|
|
322
|
+
this.flattenedFns.push(newFunctionDeclaration);
|
|
323
|
+
var argumentsName = this.getPlaceholder(); // newFn.call([...arguments], flatObject)
|
|
324
|
+
|
|
325
|
+
var callExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(newFnName), [(0, _gen.Identifier)(argumentsName), (0, _gen.Identifier)(flatObjectName)]);
|
|
326
|
+
var newObjectBody = [// var flatObject = { get(), set() };
|
|
327
|
+
(0, _gen.VariableDeclaration)([(0, _gen.VariableDeclarator)(flatObjectName, (0, _gen.ObjectExpression)(flatObjectProperties))]), (0, _gen.ReturnStatement)(newFunctionDeclaration.async ? (0, _gen.AwaitExpression)(callExpression) : callExpression)];
|
|
328
|
+
object.body = (0, _gen.BlockStatement)(newObjectBody); // Preserve function.length property
|
|
329
|
+
|
|
330
|
+
var originalFunctionLength = (0, _insert.computeFunctionLength)(object.params);
|
|
331
|
+
object.params = [(0, _gen.SpreadElement)((0, _gen.Identifier)(argumentsName))];
|
|
332
|
+
|
|
333
|
+
if (originalFunctionLength !== 0) {
|
|
334
|
+
if (!this.functionLengthName) {
|
|
335
|
+
this.functionLengthName = this.getPlaceholder();
|
|
336
|
+
(0, _insert.prepend)(parents[parents.length - 1] || object, _functionLength.FunctionLengthTemplate.single({
|
|
337
|
+
name: this.functionLengthName
|
|
338
|
+
}));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (object.type === "FunctionDeclaration") {
|
|
342
|
+
var body = parents[0];
|
|
343
|
+
|
|
344
|
+
if (Array.isArray(body)) {
|
|
345
|
+
var index = body.indexOf(object);
|
|
346
|
+
body.splice(index + 1, 0, (0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [(0, _gen.Identifier)(object.id.name), (0, _gen.Literal)(originalFunctionLength)])));
|
|
347
|
+
}
|
|
348
|
+
} else {
|
|
349
|
+
(0, _assert.ok)(object.type === "FunctionExpression");
|
|
350
|
+
this.replace(object, (0, _gen.CallExpression)((0, _gen.Identifier)(this.functionLengthName), [{ ...object
|
|
351
|
+
}, (0, _gen.Literal)(originalFunctionLength)]));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
277
354
|
};
|
|
278
355
|
}
|
|
279
356
|
|
|
@@ -17,10 +17,6 @@ var _assert = require("assert");
|
|
|
17
17
|
|
|
18
18
|
var _order = require("../../order");
|
|
19
19
|
|
|
20
|
-
var _identifiers = require("../../util/identifiers");
|
|
21
|
-
|
|
22
|
-
var _scope = require("../../util/scope");
|
|
23
|
-
|
|
24
20
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
21
|
|
|
26
22
|
/**
|
|
@@ -32,94 +28,51 @@ class MovedDeclarations extends _transform.default {
|
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
match(object, parents) {
|
|
35
|
-
return
|
|
31
|
+
return object.type === "VariableDeclaration" && object.kind === "var" && object.declarations.length === 1 && object.declarations[0].id.type === "Identifier";
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
transform(object, parents) {
|
|
39
35
|
return () => {
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
illegal.add(o.name);
|
|
62
|
-
} else {
|
|
63
|
-
defined.add(o.name);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
36
|
+
var forInitializeType = (0, _insert.isForInitialize)(object, parents); // Get the block statement or Program node
|
|
37
|
+
|
|
38
|
+
var blockIndex = parents.findIndex(x => (0, _traverse.isBlock)(x));
|
|
39
|
+
var block = parents[blockIndex];
|
|
40
|
+
var body = block.body;
|
|
41
|
+
var bodyObject = parents[blockIndex - 2] || object; // Make sure in the block statement, and not already at the top of it
|
|
42
|
+
|
|
43
|
+
var index = body.indexOf(bodyObject);
|
|
44
|
+
if (index === -1 || index === 0) return;
|
|
45
|
+
var topVariableDeclaration;
|
|
46
|
+
|
|
47
|
+
if (body[0].type === "VariableDeclaration" && body[0].kind === "var") {
|
|
48
|
+
topVariableDeclaration = body[0];
|
|
49
|
+
} else {
|
|
50
|
+
topVariableDeclaration = {
|
|
51
|
+
type: "VariableDeclaration",
|
|
52
|
+
declarations: [],
|
|
53
|
+
kind: "var"
|
|
54
|
+
};
|
|
55
|
+
(0, _insert.prepend)(block, topVariableDeclaration);
|
|
56
|
+
}
|
|
69
57
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
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);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
variableDeclarations[name] = {
|
|
96
|
-
location: [o, p],
|
|
97
|
-
replace: replace
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
};
|
|
58
|
+
var varName = object.declarations[0].id.name;
|
|
59
|
+
(0, _assert.ok)(typeof varName === "string"); // Add `var x` at the top of the block
|
|
60
|
+
|
|
61
|
+
topVariableDeclaration.declarations.push((0, _gen.VariableDeclarator)((0, _gen.Identifier)(varName)));
|
|
62
|
+
var assignmentExpression = (0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(varName), object.declarations[0].init || (0, _gen.Identifier)(varName));
|
|
63
|
+
|
|
64
|
+
if (forInitializeType) {
|
|
65
|
+
if (forInitializeType === "initializer") {
|
|
66
|
+
// Replace `for (var i = 0...)` to `for (i = 0...)`
|
|
67
|
+
this.replace(object, assignmentExpression);
|
|
68
|
+
} else if (forInitializeType === "left-hand") {
|
|
69
|
+
// Replace `for (var k in...)` to `for (k in ...)`
|
|
70
|
+
this.replace(object, (0, _gen.Identifier)(varName));
|
|
101
71
|
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
106
|
-
var movingNames = Object.keys(variableDeclarations);
|
|
107
|
-
|
|
108
|
-
if (movingNames.length === 0) {
|
|
109
|
-
return;
|
|
72
|
+
} else {
|
|
73
|
+
// Replace `var x = value` to `x = value`
|
|
74
|
+
this.replace(object, (0, _gen.ExpressionStatement)(assignmentExpression));
|
|
110
75
|
}
|
|
111
|
-
|
|
112
|
-
var variableDeclaration = (0, _gen.VariableDeclaration)(movingNames.map(name => {
|
|
113
|
-
return (0, _gen.VariableDeclarator)(name);
|
|
114
|
-
}));
|
|
115
|
-
(0, _insert.prepend)(object, variableDeclaration);
|
|
116
|
-
movingNames.forEach(name => {
|
|
117
|
-
var {
|
|
118
|
-
location,
|
|
119
|
-
replace
|
|
120
|
-
} = variableDeclarations[name];
|
|
121
|
-
this.replace(location[0], replace);
|
|
122
|
-
});
|
|
123
76
|
};
|
|
124
77
|
}
|
|
125
78
|
|