js-confuser 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +215 -172
- 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 +10 -1
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +95 -59
- package/dist/transforms/extraction/objectExtraction.js +6 -1
- 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 +145 -244
- 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 +38 -4
- package/dist/util/insert.js +24 -3
- package/docs/ControlFlowFlattening.md +595 -0
- package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
- package/docs/ES5.md +197 -0
- package/{Integrity.md → docs/Integrity.md} +2 -2
- package/docs/RGF.md +419 -0
- package/package.json +2 -2
- 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 +15 -1
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +135 -130
- package/src/transforms/extraction/objectExtraction.ts +4 -0
- 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 +221 -402
- 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 +48 -4
- package/src/util/insert.ts +26 -2
- package/test/code/ES6.src.js +24 -0
- package/test/transforms/dispatcher.test.ts +27 -0
- package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +21 -8
- package/test/transforms/extraction/objectExtraction.test.ts +35 -15
- package/test/transforms/flatten.test.ts +352 -88
- package/test/transforms/identifier/globalConcealing.test.ts +23 -2
- package/test/transforms/identifier/movedDeclarations.test.ts +37 -9
- package/test/transforms/identifier/renameVariables.test.ts +37 -0
- package/test/transforms/lock/integrity.test.ts +24 -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 +134 -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
package/dist/options.js
CHANGED
|
@@ -12,7 +12,7 @@ var _presets = _interopRequireDefault(require("./presets"));
|
|
|
12
12
|
|
|
13
13
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
14
|
|
|
15
|
-
const validProperties = new Set(["preset", "target", "indent", "compact", "hexadecimalNumbers", "minify", "es5", "renameVariables", "renameGlobals", "identifierGenerator", "
|
|
15
|
+
const validProperties = new Set(["preset", "target", "indent", "compact", "hexadecimalNumbers", "minify", "es5", "renameVariables", "renameGlobals", "identifierGenerator", "controlFlowFlattening", "globalConcealing", "stringCompression", "stringConcealing", "stringEncoding", "stringSplitting", "duplicateLiteralsRemoval", "dispatcher", "rgf", "objectExtraction", "flatten", "deadCode", "calculator", "lock", "movedDeclarations", "opaquePredicates", "shuffle", "stack", "verbose", "globalVariables", "debugComments"]);
|
|
16
16
|
const validOses = new Set(["windows", "linux", "osx", "ios", "android"]);
|
|
17
17
|
const validBrowsers = new Set(["firefox", "chrome", "iexplorer", "edge", "safari", "opera"]);
|
|
18
18
|
|
|
@@ -117,13 +117,13 @@ async function correctOptions(options) {
|
|
|
117
117
|
|
|
118
118
|
if (options.target == "browser") {
|
|
119
119
|
// browser
|
|
120
|
-
["window", "document", "postMessage", "alert", "confirm", "location"].forEach(x => options.globalVariables.add(x));
|
|
120
|
+
["window", "document", "postMessage", "alert", "confirm", "location", "btoa", "atob", "unescape", "encodeURIComponent"].forEach(x => options.globalVariables.add(x));
|
|
121
121
|
} else {
|
|
122
122
|
// node
|
|
123
|
-
["global", "Buffer", "require", "process", "__dirname", "__filename"].forEach(x => options.globalVariables.add(x));
|
|
123
|
+
["global", "Buffer", "require", "process", "exports", "module", "__dirname", "__filename"].forEach(x => options.globalVariables.add(x));
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
["globalThis", "console", "parseInt", "parseFloat", "Math", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "
|
|
126
|
+
["globalThis", "console", "parseInt", "parseFloat", "Math", "JSON", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "isNaN", "isFinite", "Set", "Map", "WeakSet", "WeakMap", "Symbol"].forEach(x => options.globalVariables.add(x));
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
return options;
|
package/dist/presets.js
CHANGED
|
@@ -22,7 +22,7 @@ exports.default = void 0;
|
|
|
22
22
|
* 10. Minified output
|
|
23
23
|
*
|
|
24
24
|
* ## **`Disabled features`**
|
|
25
|
-
* - `
|
|
25
|
+
* - `rgf` Use at your own risk!
|
|
26
26
|
*
|
|
27
27
|
* ### Potential Issues
|
|
28
28
|
* 1. *String Encoding* can corrupt files. Disable `stringEncoding` manually if this happens.
|
|
@@ -57,7 +57,6 @@ const highPreset = {
|
|
|
57
57
|
stringEncoding: true,
|
|
58
58
|
stringSplitting: 0.75,
|
|
59
59
|
// Use at own risk
|
|
60
|
-
eval: false,
|
|
61
60
|
rgf: false
|
|
62
61
|
};
|
|
63
62
|
/**
|
|
@@ -71,9 +70,9 @@ const mediumPreset = {
|
|
|
71
70
|
calculator: true,
|
|
72
71
|
compact: true,
|
|
73
72
|
hexadecimalNumbers: true,
|
|
74
|
-
controlFlowFlattening: 0.
|
|
73
|
+
controlFlowFlattening: 0.25,
|
|
75
74
|
deadCode: 0.025,
|
|
76
|
-
dispatcher: 0.
|
|
75
|
+
dispatcher: 0.5,
|
|
77
76
|
duplicateLiteralsRemoval: 0.5,
|
|
78
77
|
globalConcealing: true,
|
|
79
78
|
identifierGenerator: "randomized",
|
|
@@ -99,10 +98,10 @@ const lowPreset = {
|
|
|
99
98
|
calculator: true,
|
|
100
99
|
compact: true,
|
|
101
100
|
hexadecimalNumbers: true,
|
|
102
|
-
controlFlowFlattening: 0.
|
|
101
|
+
controlFlowFlattening: 0.1,
|
|
103
102
|
deadCode: 0.01,
|
|
104
|
-
dispatcher: 0.
|
|
105
|
-
duplicateLiteralsRemoval:
|
|
103
|
+
dispatcher: 0.25,
|
|
104
|
+
duplicateLiteralsRemoval: 0.5,
|
|
106
105
|
identifierGenerator: "randomized",
|
|
107
106
|
minify: true,
|
|
108
107
|
movedDeclarations: true,
|
package/dist/templates/crash.js
CHANGED
|
@@ -9,9 +9,9 @@ var _template = _interopRequireDefault(require("./template"));
|
|
|
9
9
|
|
|
10
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
11
|
|
|
12
|
-
const CrashTemplate1 = (0, _template.default)("\nvar {var} = \"a\";\nwhile(1){\n {var} = {var} += \"a\"
|
|
12
|
+
const CrashTemplate1 = (0, _template.default)("\nvar {var} = \"a\";\nwhile(1){\n {var} = {var} += \"a\";\n}\n");
|
|
13
13
|
exports.CrashTemplate1 = CrashTemplate1;
|
|
14
14
|
const CrashTemplate2 = (0, _template.default)("\nwhile(true) {\n var {var} = 99;\n for({var} = 99; {var} == {var}; {var} *= {var}) {\n !{var} && console.log({var});\n if ({var} <= 10){\n break;\n }\n };\n if({var} === 100) {\n {var}--\n }\n };");
|
|
15
15
|
exports.CrashTemplate2 = CrashTemplate2;
|
|
16
|
-
const CrashTemplate3 = (0, _template.default)("\ntry {\n function {$2}(y, x){\n return x;\n }\n \n var {$1} = {$2}(this, function () {\n var {$3} = function () {\n var regExp = {$3}\n .constructor('return /\" + this + \"/')()\n .constructor('^([^ ]+( +[^ ]+)+)+[^ ]}');\n \n return !regExp.call({$1});\n };\n \n return {$3}();\n });\n \n {$1}();\n} catch ( e ) {\n while(e ? e : !e){\n var b;\n var c = 0;\n (e ? !e : e) ? (function(e){\n c = e ? 0 : !e ? 1 : 0;\n })(e) : b = 1;\n\n if(b&&c){break;}\n if(b){continue;}\n }\n}\n");
|
|
16
|
+
const CrashTemplate3 = (0, _template.default)("\ntry {\n function {$2}(y, x){\n return x;\n }\n \n var {$1} = {$2}(this, function () {\n var {$3} = function () {\n var regExp = {$3}\n .constructor('return /\" + this + \"/')()\n .constructor('^([^ ]+( +[^ ]+)+)+[^ ]}');\n \n return !regExp.call({$1});\n };\n \n return {$3}();\n });\n \n {$1}();\n} catch ( {$1}e ) {\n while({$1}e ? {$1}e : !{$1}e){\n var {$1}b;\n var {$1}c = 0;\n ({$1}e ? !{$1}e : {$1}e) ? (function({$1}e){\n {$1}c = {$1}e ? 0 : !{$1}e ? 1 : 0;\n })({$1}e) : {$1}b = 1;\n\n if({$1}b&&{$1}c){break;}\n if({$1}b){continue;}\n }\n}\n");
|
|
17
17
|
exports.CrashTemplate3 = CrashTemplate3;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FunctionLengthTemplate = void 0;
|
|
7
|
+
|
|
8
|
+
var _template = _interopRequireDefault(require("./template"));
|
|
9
|
+
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Helper function to set `function.length` property.
|
|
14
|
+
*/
|
|
15
|
+
const FunctionLengthTemplate = (0, _template.default)("\nfunction {name}(functionObject, functionLength){\n Object[\"defineProperty\"](functionObject, \"length\", {\n \"value\": functionLength,\n \"configurable\": true\n });\n return functionObject;\n}\n");
|
|
16
|
+
exports.FunctionLengthTemplate = FunctionLengthTemplate;
|
|
@@ -56,9 +56,12 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
56
56
|
* 3. using `this`
|
|
57
57
|
*/
|
|
58
58
|
class Dispatcher extends _transform.default {
|
|
59
|
+
// Debug mode preserves function names
|
|
59
60
|
constructor(o) {
|
|
60
61
|
super(o, _order.ObfuscateOrder.Dispatcher);
|
|
61
62
|
|
|
63
|
+
_defineProperty(this, "isDebug", false);
|
|
64
|
+
|
|
62
65
|
_defineProperty(this, "count", void 0);
|
|
63
66
|
|
|
64
67
|
this.count = 0;
|
|
@@ -120,6 +123,12 @@ class Dispatcher extends _transform.default {
|
|
|
120
123
|
illegalFnNames.add(name);
|
|
121
124
|
return "EXIT";
|
|
122
125
|
}
|
|
126
|
+
} // Avoid functions with function expressions as they have a different scope
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if ((oo.type === "FunctionExpression" || oo.type === "ArrowFunctionExpression") && pp.find(x => x == o.params)) {
|
|
130
|
+
illegalFnNames.add(name);
|
|
131
|
+
return "EXIT";
|
|
123
132
|
}
|
|
124
133
|
});
|
|
125
134
|
functionDeclarations[name] = [o, p];
|
|
@@ -158,7 +167,7 @@ class Dispatcher extends _transform.default {
|
|
|
158
167
|
|
|
159
168
|
var gen = this.getGenerator();
|
|
160
169
|
Object.keys(functionDeclarations).forEach(name => {
|
|
161
|
-
newFnNames[name] = gen.generate();
|
|
170
|
+
newFnNames[name] = this.isDebug ? "_dispatcher_" + this.count + "_" + name : gen.generate();
|
|
162
171
|
}); // set containing new name
|
|
163
172
|
|
|
164
173
|
var set = new Set(Object.keys(newFnNames)); // Only make a dispatcher function if it caught any functions
|
|
@@ -23,6 +23,10 @@ var _assert = require("assert");
|
|
|
23
23
|
|
|
24
24
|
var _random = require("../../util/random");
|
|
25
25
|
|
|
26
|
+
var _traverse = require("../../traverse");
|
|
27
|
+
|
|
28
|
+
var _identifiers = require("../../util/identifiers");
|
|
29
|
+
|
|
26
30
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
31
|
|
|
28
32
|
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; }
|
|
@@ -46,12 +50,19 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
46
50
|
* ```
|
|
47
51
|
*/
|
|
48
52
|
class DuplicateLiteralsRemoval extends _transform.default {
|
|
53
|
+
// The array holding all the duplicate literals
|
|
54
|
+
// The array expression node to be inserted into the program
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Literals in the array
|
|
58
|
+
*/
|
|
59
|
+
|
|
49
60
|
/**
|
|
50
|
-
*
|
|
61
|
+
* Literals are saved here the first time they are seen.
|
|
51
62
|
*/
|
|
52
63
|
|
|
53
64
|
/**
|
|
54
|
-
*
|
|
65
|
+
* Block -> { functionName, indexShift }
|
|
55
66
|
*/
|
|
56
67
|
constructor(o) {
|
|
57
68
|
super(o, _order.ObfuscateOrder.DuplicateLiteralsRemoval);
|
|
@@ -64,23 +75,45 @@ class DuplicateLiteralsRemoval extends _transform.default {
|
|
|
64
75
|
|
|
65
76
|
_defineProperty(this, "first", void 0);
|
|
66
77
|
|
|
67
|
-
_defineProperty(this, "
|
|
68
|
-
|
|
69
|
-
_defineProperty(this, "fnGetters", void 0);
|
|
78
|
+
_defineProperty(this, "functions", void 0);
|
|
70
79
|
|
|
71
80
|
this.map = new Map();
|
|
72
81
|
this.first = new Map();
|
|
73
|
-
this.
|
|
74
|
-
this.fnGetters = new Map();
|
|
82
|
+
this.functions = new Map();
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
apply(tree) {
|
|
78
86
|
super.apply(tree);
|
|
79
87
|
|
|
80
|
-
if (this.arrayName && this.arrayExpression.elements.length) {
|
|
88
|
+
if (this.arrayName && this.arrayExpression.elements.length > 0) {
|
|
89
|
+
// This function simply returns the array
|
|
81
90
|
var getArrayFn = this.getPlaceholder();
|
|
82
|
-
(0, _insert.append)(tree, (0, _gen.FunctionDeclaration)(getArrayFn, [], [(0, _gen.ReturnStatement)(this.arrayExpression)]));
|
|
83
|
-
|
|
91
|
+
(0, _insert.append)(tree, (0, _gen.FunctionDeclaration)(getArrayFn, [], [(0, _gen.ReturnStatement)(this.arrayExpression)])); // This variable holds the array
|
|
92
|
+
|
|
93
|
+
(0, _insert.prepend)(tree, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.arrayName, (0, _gen.CallExpression)((0, _gen.MemberExpression)((0, _gen.Identifier)(getArrayFn), (0, _gen.Literal)("call"), true), [(0, _gen.ThisExpression)()])))); // Create all the functions needed
|
|
94
|
+
|
|
95
|
+
for (var blockNode of this.functions.keys()) {
|
|
96
|
+
var {
|
|
97
|
+
functionName,
|
|
98
|
+
indexShift
|
|
99
|
+
} = this.functions.get(blockNode);
|
|
100
|
+
var propertyNode = (0, _gen.BinaryExpression)("-", (0, _gen.Identifier)("index_param"), (0, _gen.Literal)(indexShift));
|
|
101
|
+
var indexRangeInclusive = [0 + indexShift - 1, this.map.size + indexShift]; // The function uses mangling to hide the index being accessed
|
|
102
|
+
|
|
103
|
+
var mangleCount = (0, _random.getRandomInteger)(1, 10);
|
|
104
|
+
|
|
105
|
+
for (var i = 0; i < mangleCount; i++) {
|
|
106
|
+
var operator = (0, _random.choice)([">", "<"]);
|
|
107
|
+
var compareValue = (0, _random.choice)(indexRangeInclusive);
|
|
108
|
+
var test = (0, _gen.BinaryExpression)(operator, (0, _gen.Identifier)("index_param"), (0, _gen.Literal)(compareValue));
|
|
109
|
+
var alternate = (0, _gen.BinaryExpression)("-", (0, _gen.Identifier)("index_param"), (0, _gen.Literal)((0, _random.getRandomInteger)(-100, 100)));
|
|
110
|
+
var testValue = operator === ">" && compareValue === indexRangeInclusive[0] || operator === "<" && compareValue === indexRangeInclusive[1];
|
|
111
|
+
propertyNode = (0, _gen.ConditionalExpression)(test, testValue ? propertyNode : alternate, !testValue ? propertyNode : alternate);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
var returnArgument = (0, _gen.MemberExpression)((0, _gen.Identifier)(this.arrayName), propertyNode, true);
|
|
115
|
+
(0, _insert.prepend)(blockNode, (0, _gen.FunctionDeclaration)(functionName, [(0, _gen.Identifier)("index_param")], [(0, _gen.ReturnStatement)(returnArgument)]));
|
|
116
|
+
}
|
|
84
117
|
}
|
|
85
118
|
}
|
|
86
119
|
|
|
@@ -95,48 +128,47 @@ class DuplicateLiteralsRemoval extends _transform.default {
|
|
|
95
128
|
*/
|
|
96
129
|
|
|
97
130
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
var getterNames = [object, ...parents].map(x => this.fnGetters.get(x)).filter(x => x); // use random getter function
|
|
101
|
-
|
|
102
|
-
var getterName = (0, _random.choice)(getterNames); // get this literals context
|
|
131
|
+
transformLiteral(object, parents, index) {
|
|
132
|
+
var blockNode = (0, _random.choice)(parents.filter(x => this.functions.has(x))); // Create initial function if none exist
|
|
103
133
|
|
|
104
|
-
|
|
105
|
-
|
|
134
|
+
if (this.functions.size === 0) {
|
|
135
|
+
var root = parents[parents.length - 1];
|
|
136
|
+
var rootFunctionName = this.getPlaceholder() + "_dLR_0";
|
|
137
|
+
this.functions.set(root, {
|
|
138
|
+
functionName: rootFunctionName,
|
|
139
|
+
indexShift: (0, _random.getRandomInteger)(-100, 100)
|
|
140
|
+
});
|
|
141
|
+
blockNode = root;
|
|
142
|
+
} // If no function here exist, possibly create new chained function
|
|
106
143
|
|
|
107
|
-
var shouldCreateNew = !getterName || !hasGetterHere && Math.random() > 0.9;
|
|
108
144
|
|
|
109
|
-
|
|
110
|
-
(0, _assert.ok)(!this.fnGetters.has(lexContext));
|
|
111
|
-
var lexContextIndex = parents.findIndex(x => x !== lexContext && (0, _insert.isLexContext)(x));
|
|
112
|
-
var basedOn = lexContextIndex !== -1 ? (0, _random.choice)(parents.slice(lexContextIndex + 1).map(x => this.fnGetters.get(x)).filter(x => x)) : null;
|
|
113
|
-
var body = [];
|
|
114
|
-
var thisShift = (0, _random.getRandomInteger)(-250, 250); // the name of the getter
|
|
145
|
+
var block = (0, _traverse.getBlock)(object, parents);
|
|
115
146
|
|
|
116
|
-
|
|
147
|
+
if (!this.functions.has(block) && (0, _random.chance)(50 - this.functions.size)) {
|
|
148
|
+
var newFunctionName = this.getPlaceholder() + "_dLR_" + this.functions.size;
|
|
149
|
+
this.functions.set(block, {
|
|
150
|
+
functionName: newFunctionName,
|
|
151
|
+
indexShift: (0, _random.getRandomInteger)(-100, 100)
|
|
152
|
+
});
|
|
153
|
+
blockNode = block;
|
|
154
|
+
} // Derive the function to call from the selected blockNode
|
|
117
155
|
|
|
118
|
-
if (basedOn) {
|
|
119
|
-
var shift = this.fnShifts.get(basedOn);
|
|
120
|
-
(0, _assert.ok)(typeof shift === "number");
|
|
121
|
-
body = [(0, _gen.ReturnStatement)((0, _gen.CallExpression)((0, _gen.Identifier)(basedOn), [(0, _gen.BinaryExpression)("+", (0, _gen.Identifier)("index"), (0, _gen.Literal)(thisShift))]))];
|
|
122
|
-
this.fnShifts.set(getterName, shift + thisShift);
|
|
123
|
-
} else {
|
|
124
|
-
// from scratch
|
|
125
|
-
body = [(0, _gen.ReturnStatement)((0, _gen.MemberExpression)((0, _gen.Identifier)(this.arrayName), (0, _gen.BinaryExpression)("+", (0, _gen.Identifier)("index"), (0, _gen.Literal)(thisShift)), true))];
|
|
126
|
-
this.fnShifts.set(getterName, thisShift);
|
|
127
|
-
}
|
|
128
156
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
157
|
+
var {
|
|
158
|
+
functionName,
|
|
159
|
+
indexShift
|
|
160
|
+
} = this.functions.get(blockNode); // Call the function given it's indexShift
|
|
132
161
|
|
|
133
|
-
var
|
|
134
|
-
this.replaceIdentifierOrLiteral(object,
|
|
162
|
+
var callExpression = (0, _gen.CallExpression)((0, _gen.Identifier)(functionName), [(0, _gen.Literal)(index + indexShift)]);
|
|
163
|
+
this.replaceIdentifierOrLiteral(object, callExpression, parents);
|
|
135
164
|
}
|
|
136
165
|
|
|
137
166
|
transform(object, parents) {
|
|
138
167
|
return () => {
|
|
139
|
-
|
|
168
|
+
if (object.type === "Identifier") {
|
|
169
|
+
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
|
|
170
|
+
if (info.isLabel || info.spec.isDefined) return;
|
|
171
|
+
}
|
|
140
172
|
|
|
141
173
|
if (object.regex) {
|
|
142
174
|
return;
|
|
@@ -147,19 +179,19 @@ class DuplicateLiteralsRemoval extends _transform.default {
|
|
|
147
179
|
} // HARD CODED LIMIT of 10,000 (after 1,000 elements)
|
|
148
180
|
|
|
149
181
|
|
|
150
|
-
if (this.map.size > 1000 &&
|
|
182
|
+
if (this.map.size > 1000 && (0, _random.chance)(this.map.size / 100)) return;
|
|
151
183
|
|
|
152
184
|
if (this.arrayName && parents[0].object && parents[0].object.name == this.arrayName) {
|
|
153
185
|
return;
|
|
154
186
|
}
|
|
155
187
|
|
|
156
|
-
var
|
|
188
|
+
var stringValue;
|
|
157
189
|
|
|
158
190
|
if (object.type == "Literal") {
|
|
159
|
-
|
|
191
|
+
stringValue = typeof object.value + ":" + object.value;
|
|
160
192
|
|
|
161
193
|
if (object.value === null) {
|
|
162
|
-
|
|
194
|
+
stringValue = "null:null";
|
|
163
195
|
} else {
|
|
164
196
|
// Skip empty strings
|
|
165
197
|
if (typeof object.value === "string" && !object.value) {
|
|
@@ -167,38 +199,42 @@ class DuplicateLiteralsRemoval extends _transform.default {
|
|
|
167
199
|
}
|
|
168
200
|
}
|
|
169
201
|
} else if (object.type == "Identifier") {
|
|
170
|
-
|
|
202
|
+
stringValue = "identifier:" + object.name;
|
|
171
203
|
} else {
|
|
172
204
|
throw new Error("Unsupported primitive type: " + object.type);
|
|
173
205
|
}
|
|
174
206
|
|
|
175
|
-
(0, _assert.ok)(
|
|
207
|
+
(0, _assert.ok)(stringValue);
|
|
176
208
|
|
|
177
|
-
if (
|
|
178
|
-
|
|
179
|
-
} else {
|
|
209
|
+
if (this.map.has(stringValue) || this.first.has(stringValue)) {
|
|
210
|
+
// Create the array if not already made
|
|
180
211
|
if (!this.arrayName) {
|
|
181
212
|
this.arrayName = this.getPlaceholder();
|
|
182
213
|
this.arrayExpression = (0, _gen.ArrayExpression)([]);
|
|
183
|
-
}
|
|
214
|
+
} // Delete with first location
|
|
184
215
|
|
|
185
|
-
|
|
216
|
+
|
|
217
|
+
var firstLocation = this.first.get(stringValue);
|
|
186
218
|
|
|
187
219
|
if (firstLocation) {
|
|
188
|
-
this.first.set(value, null);
|
|
189
220
|
var index = this.map.size;
|
|
190
|
-
(0, _assert.ok)(!this.map.has(
|
|
191
|
-
this.map.set(
|
|
221
|
+
(0, _assert.ok)(!this.map.has(stringValue));
|
|
222
|
+
this.map.set(stringValue, index);
|
|
223
|
+
this.first.delete(stringValue);
|
|
192
224
|
var pushing = (0, _insert.clone)(object);
|
|
193
225
|
this.arrayExpression.elements.push(pushing);
|
|
194
226
|
(0, _assert.ok)(this.arrayExpression.elements[index] === pushing);
|
|
195
|
-
this.
|
|
227
|
+
this.transformLiteral(firstLocation[0], firstLocation[1], index);
|
|
196
228
|
}
|
|
197
229
|
|
|
198
|
-
var index = this.map.get(
|
|
230
|
+
var index = this.map.get(stringValue);
|
|
199
231
|
(0, _assert.ok)(typeof index === "number");
|
|
200
|
-
this.
|
|
201
|
-
|
|
232
|
+
this.transformLiteral(object, parents, index);
|
|
233
|
+
return;
|
|
234
|
+
} // Save this, maybe a duplicate will be found.
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
this.first.set(stringValue, [object, parents]);
|
|
202
238
|
};
|
|
203
239
|
}
|
|
204
240
|
|
|
@@ -236,7 +236,12 @@ class ObjectExtraction extends _transform.default {
|
|
|
236
236
|
var v = property.value;
|
|
237
237
|
variableDeclarators.push((0, _gen.VariableDeclarator)(nn, this.addComment(v, "".concat(name, ".").concat(keyName))));
|
|
238
238
|
});
|
|
239
|
-
declaration.declarations.splice(declaration.declarations.indexOf(declarator), 1, ...variableDeclarators);
|
|
239
|
+
declaration.declarations.splice(declaration.declarations.indexOf(declarator), 1, ...variableDeclarators);
|
|
240
|
+
|
|
241
|
+
if (declaration.kind === "const") {
|
|
242
|
+
declaration.kind = "var";
|
|
243
|
+
} // update all identifiers that pointed to the old object
|
|
244
|
+
|
|
240
245
|
|
|
241
246
|
objectDefChanges[name] && objectDefChanges[name].forEach(change => {
|
|
242
247
|
if (!change.key) {
|