js-confuser 1.5.9 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +55 -0
- package/README.md +346 -165
- package/dist/constants.js +6 -2
- package/dist/index.js +9 -21
- package/dist/obfuscator.js +19 -31
- package/dist/options.js +5 -5
- package/dist/order.js +1 -3
- package/dist/presets.js +6 -7
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +3 -3
- package/dist/templates/es5.js +18 -0
- package/dist/templates/functionLength.js +16 -0
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -1
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +8 -4
- package/dist/transforms/es5/antiDestructuring.js +2 -0
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +92 -58
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +229 -148
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +35 -88
- package/dist/transforms/identifier/renameVariables.js +124 -59
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/lock/lock.js +0 -37
- package/dist/transforms/minify.js +60 -57
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +139 -247
- package/dist/transforms/stack.js +128 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +12 -19
- package/dist/traverse.js +24 -10
- package/dist/util/gen.js +17 -1
- package/dist/util/identifiers.js +37 -3
- package/dist/util/insert.js +35 -4
- package/dist/util/random.js +15 -0
- package/docs/ControlFlowFlattening.md +595 -0
- package/{Countermeasures.md → docs/Countermeasures.md} +1 -15
- package/{Integrity.md → docs/Integrity.md} +2 -2
- package/docs/RGF.md +419 -0
- package/package.json +5 -5
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -2
- package/src/obfuscator.ts +19 -31
- package/src/options.ts +14 -103
- package/src/order.ts +1 -5
- package/src/presets.ts +6 -7
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +15 -19
- package/src/templates/es5.ts +131 -0
- package/src/templates/functionLength.ts +14 -0
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +4 -1
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +9 -4
- package/src/transforms/es5/antiDestructuring.ts +2 -0
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +133 -129
- package/src/transforms/{hexadecimalNumbers.ts → finalizer.ts} +29 -13
- package/src/transforms/flatten.ts +357 -300
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +49 -102
- package/src/transforms/identifier/renameVariables.ts +149 -78
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/lock/lock.ts +1 -42
- package/src/transforms/minify.ts +91 -75
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +213 -405
- package/src/transforms/stack.ts +156 -36
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +39 -9
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +21 -23
- package/src/traverse.ts +23 -4
- package/src/types.ts +2 -1
- package/src/util/gen.ts +28 -3
- package/src/util/identifiers.ts +43 -2
- package/src/util/insert.ts +38 -3
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +146 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/index.test.ts +2 -1
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +22 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +702 -160
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +20 -1
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/flatten.test.ts +399 -86
- package/test/transforms/identifier/movedDeclarations.test.ts +63 -8
- package/test/transforms/identifier/renameVariables.test.ts +119 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/lock/lock.test.ts +1 -48
- package/test/transforms/minify.test.ts +104 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +261 -381
- package/test/transforms/stack.test.ts +143 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +82 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/identifiers.test.ts +113 -1
- package/test/util/insert.test.ts +57 -3
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/eval.ts +0 -89
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/identifier/nameRecycling.ts +0 -280
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/eval.test.ts +0 -131
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/identifier/nameRecycling.test.ts +0 -205
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
import { ok } from "assert";
|
|
2
2
|
import { ObfuscateOrder } from "../../order";
|
|
3
3
|
import { walk } from "../../traverse";
|
|
4
|
-
import {
|
|
4
|
+
import { Node } from "../../util/gen";
|
|
5
5
|
import { getIdentifierInfo } from "../../util/identifiers";
|
|
6
6
|
import {
|
|
7
|
-
getVarContext,
|
|
8
7
|
isVarContext,
|
|
9
|
-
getLexContext,
|
|
10
8
|
isContext,
|
|
11
9
|
isLexContext,
|
|
12
|
-
getDefiningContext,
|
|
13
10
|
clone,
|
|
11
|
+
isFunction,
|
|
14
12
|
} from "../../util/insert";
|
|
15
|
-
import { isValidIdentifier } from "../../util/compare";
|
|
16
13
|
import Transform from "../transform";
|
|
17
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
noRenameVariablePrefix,
|
|
16
|
+
placeholderVariablePrefix,
|
|
17
|
+
reservedIdentifiers,
|
|
18
|
+
} from "../../constants";
|
|
18
19
|
import { ComputeProbabilityMap } from "../../probability";
|
|
19
20
|
import VariableAnalysis from "./variableAnalysis";
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Rename variables to randomly generated names.
|
|
23
24
|
*
|
|
24
|
-
* -
|
|
25
|
+
* - 1. First collect data on identifiers in all scope using 'VariableAnalysis'
|
|
26
|
+
* - 2. After 'VariableAnalysis' is finished start applying to each scope (top-down)
|
|
27
|
+
* - 3. Each scope, find the all names used here and exclude those names from being re-named
|
|
28
|
+
* - 4. Now loop through all the defined names in this scope and set it to a random name (or re-use previously generated name)
|
|
29
|
+
* - 5. Update all the Identifiers node's 'name' property to reflect this change
|
|
25
30
|
*/
|
|
26
31
|
export default class RenameVariables extends Transform {
|
|
27
|
-
// Generator object
|
|
28
|
-
gen: any;
|
|
29
|
-
|
|
30
32
|
// Names already used
|
|
31
33
|
generated: string[];
|
|
32
34
|
|
|
@@ -36,22 +38,26 @@ export default class RenameVariables extends Transform {
|
|
|
36
38
|
// Ref to VariableAnalysis data
|
|
37
39
|
variableAnalysis: VariableAnalysis;
|
|
38
40
|
|
|
41
|
+
// Option to re-use previously generated names
|
|
42
|
+
reusePreviousNames = true;
|
|
43
|
+
|
|
39
44
|
constructor(o) {
|
|
40
45
|
super(o, ObfuscateOrder.RenameVariables);
|
|
41
46
|
|
|
42
47
|
this.changed = new Map();
|
|
43
48
|
|
|
49
|
+
// 1.
|
|
44
50
|
this.variableAnalysis = new VariableAnalysis(o);
|
|
45
51
|
this.before.push(this.variableAnalysis);
|
|
46
|
-
this.gen = this.getGenerator();
|
|
47
52
|
this.generated = [];
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
match(object, parents) {
|
|
51
|
-
return isContext(object);
|
|
55
|
+
match(object: Node, parents: Node[]) {
|
|
56
|
+
return isContext(object) || object.type === "Identifier";
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
transformContext(object: Node, parents: Node[]) {
|
|
60
|
+
// 2. Notice this is on 'onEnter' (top-down)
|
|
55
61
|
var isGlobal = object.type == "Program";
|
|
56
62
|
var type = isGlobal
|
|
57
63
|
? "root"
|
|
@@ -68,15 +74,18 @@ export default class RenameVariables extends Transform {
|
|
|
68
74
|
var defined = this.variableAnalysis.defined.get(object) || new Set();
|
|
69
75
|
var references = this.variableAnalysis.references.get(object) || new Set();
|
|
70
76
|
|
|
77
|
+
// No changes needed here
|
|
71
78
|
if (!defined && !this.changed.has(object)) {
|
|
72
79
|
this.changed.set(object, Object.create(null));
|
|
73
80
|
return;
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
// Names possible to be re-used here
|
|
84
|
+
var possible = new Set<string>();
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
// 3. Try to re-use names when possible
|
|
87
|
+
if (this.reusePreviousNames && this.generated.length && !isGlobal) {
|
|
88
|
+
var allReferences = new Set<string>();
|
|
80
89
|
var nope = new Set(defined);
|
|
81
90
|
walk(object, [], (o, p) => {
|
|
82
91
|
var ref = this.variableAnalysis.references.get(o);
|
|
@@ -90,14 +99,14 @@ export default class RenameVariables extends Transform {
|
|
|
90
99
|
}
|
|
91
100
|
});
|
|
92
101
|
|
|
93
|
-
var passed = new Set();
|
|
102
|
+
var passed = new Set<string>();
|
|
94
103
|
parents.forEach((p) => {
|
|
95
104
|
var changes = this.changed.get(p);
|
|
96
105
|
if (changes) {
|
|
97
106
|
Object.keys(changes).forEach((x) => {
|
|
98
107
|
var name = changes[x];
|
|
99
108
|
|
|
100
|
-
if (!allReferences.has(x)) {
|
|
109
|
+
if (!allReferences.has(x) && !references.has(x)) {
|
|
101
110
|
passed.add(name);
|
|
102
111
|
} else {
|
|
103
112
|
nope.add(name);
|
|
@@ -111,104 +120,166 @@ export default class RenameVariables extends Transform {
|
|
|
111
120
|
possible = passed;
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
|
|
123
|
+
// 4. Defined names to new names
|
|
124
|
+
for (var name of defined) {
|
|
115
125
|
if (
|
|
116
|
-
|
|
126
|
+
!name.startsWith(noRenameVariablePrefix) && // Variables prefixed with '__NO_JS_CONFUSER_RENAME__' are never renamed
|
|
127
|
+
(isGlobal && !name.startsWith(placeholderVariablePrefix) // Variables prefixed with '__p_' are created by the obfuscator, always renamed
|
|
117
128
|
? ComputeProbabilityMap(this.options.renameGlobals, (x) => x, name)
|
|
118
129
|
: true) &&
|
|
119
130
|
ComputeProbabilityMap(
|
|
131
|
+
// Check the user's option for renaming variables
|
|
120
132
|
this.options.renameVariables,
|
|
121
133
|
(x) => x,
|
|
122
134
|
name,
|
|
123
135
|
isGlobal
|
|
124
136
|
)
|
|
125
137
|
) {
|
|
126
|
-
//
|
|
127
|
-
var newName;
|
|
138
|
+
// Create a new name from (1) or (2) methods
|
|
139
|
+
var newName: string;
|
|
128
140
|
do {
|
|
129
141
|
if (possible.size) {
|
|
142
|
+
// (1) Re-use previously generated name
|
|
130
143
|
var first = possible.values().next().value;
|
|
131
144
|
possible.delete(first);
|
|
132
145
|
newName = first;
|
|
133
146
|
} else {
|
|
134
|
-
//
|
|
135
|
-
var
|
|
147
|
+
// (2) Create a new name with `generateIdentifier` function
|
|
148
|
+
var generatedName = this.generateIdentifier();
|
|
136
149
|
|
|
137
|
-
newName =
|
|
138
|
-
this.generated.push(
|
|
150
|
+
newName = generatedName;
|
|
151
|
+
this.generated.push(generatedName);
|
|
139
152
|
}
|
|
140
|
-
} while (this.variableAnalysis.globals.has(newName));
|
|
153
|
+
} while (this.variableAnalysis.globals.has(newName)); // Ensure global names aren't overridden
|
|
141
154
|
|
|
142
155
|
newNames[name] = newName;
|
|
143
156
|
} else {
|
|
157
|
+
// This variable name was deemed not to be renamed.
|
|
144
158
|
newNames[name] = name;
|
|
145
159
|
}
|
|
146
|
-
}
|
|
160
|
+
}
|
|
147
161
|
|
|
162
|
+
// console.log(object.type, newNames);
|
|
148
163
|
this.changed.set(object, newNames);
|
|
164
|
+
}
|
|
149
165
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
166
|
+
transformIdentifier(object: Node, parents: Node[]) {
|
|
167
|
+
const identifierName = object.name;
|
|
168
|
+
if (
|
|
169
|
+
reservedIdentifiers.has(identifierName) ||
|
|
170
|
+
this.options.globalVariables.has(identifierName)
|
|
171
|
+
) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (object.$renamed) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
158
178
|
|
|
159
|
-
|
|
179
|
+
var info = getIdentifierInfo(object, parents);
|
|
160
180
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
181
|
+
if (info.spec.isExported) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
164
184
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
185
|
+
if (!info.spec.isReferenced) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
var contexts = [object, ...parents].filter((x) => isContext(x));
|
|
190
|
+
var newName = null;
|
|
191
|
+
|
|
192
|
+
// Function default parameter check!
|
|
193
|
+
var functionIndices = [];
|
|
194
|
+
for (var i in parents) {
|
|
195
|
+
if (isFunction(parents[i])) {
|
|
196
|
+
functionIndices.push(i);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
168
199
|
|
|
169
|
-
|
|
170
|
-
|
|
200
|
+
for (var functionIndex of functionIndices) {
|
|
201
|
+
if (parents[functionIndex].id === object) {
|
|
202
|
+
// This context is not referenced, so remove it
|
|
203
|
+
contexts = contexts.filter(
|
|
204
|
+
(context) => context != parents[functionIndex]
|
|
205
|
+
);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (parents[functionIndex].params === parents[functionIndex - 1]) {
|
|
209
|
+
var isReferencedHere = true;
|
|
210
|
+
|
|
211
|
+
var slicedParents = parents.slice(0, functionIndex);
|
|
212
|
+
var forIndex = 0;
|
|
213
|
+
for (var parent of slicedParents) {
|
|
214
|
+
var childNode = slicedParents[forIndex - 1] || object;
|
|
171
215
|
|
|
172
|
-
for (var check of contexts) {
|
|
173
216
|
if (
|
|
174
|
-
|
|
175
|
-
|
|
217
|
+
parent.type === "AssignmentPattern" &&
|
|
218
|
+
parent.right === childNode
|
|
176
219
|
) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
220
|
+
isReferencedHere = false;
|
|
221
|
+
break;
|
|
181
222
|
}
|
|
223
|
+
|
|
224
|
+
forIndex++;
|
|
182
225
|
}
|
|
183
226
|
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
227
|
+
if (!isReferencedHere) {
|
|
228
|
+
// This context is not referenced, so remove it
|
|
229
|
+
contexts = contexts.filter(
|
|
230
|
+
(context) => context != parents[functionIndex]
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
188
235
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
236
|
+
for (var check of contexts) {
|
|
237
|
+
if (
|
|
238
|
+
this.variableAnalysis.defined.has(check) &&
|
|
239
|
+
this.variableAnalysis.defined.get(check).has(identifierName)
|
|
240
|
+
) {
|
|
241
|
+
if (
|
|
242
|
+
this.changed.has(check) &&
|
|
243
|
+
this.changed.get(check)[identifierName]
|
|
244
|
+
) {
|
|
245
|
+
newName = this.changed.get(check)[identifierName];
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
206
250
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
251
|
+
if (newName && typeof newName === "string") {
|
|
252
|
+
// Strange behavior where the `local` and `imported` objects are the same
|
|
253
|
+
if (info.isImportSpecifier) {
|
|
254
|
+
var importSpecifierIndex = parents.findIndex(
|
|
255
|
+
(x) => x.type === "ImportSpecifier"
|
|
256
|
+
);
|
|
257
|
+
if (
|
|
258
|
+
importSpecifierIndex != -1 &&
|
|
259
|
+
parents[importSpecifierIndex].imported ===
|
|
260
|
+
(parents[importSpecifierIndex - 1] || object) &&
|
|
261
|
+
parents[importSpecifierIndex].imported &&
|
|
262
|
+
parents[importSpecifierIndex].imported.type === "Identifier"
|
|
263
|
+
) {
|
|
264
|
+
parents[importSpecifierIndex].imported = clone(
|
|
265
|
+
parents[importSpecifierIndex - 1] || object
|
|
266
|
+
);
|
|
210
267
|
}
|
|
211
268
|
}
|
|
212
|
-
|
|
269
|
+
|
|
270
|
+
// console.log(o.name, "->", newName);
|
|
271
|
+
// 5. Update Identifier node's 'name' property
|
|
272
|
+
object.name = newName;
|
|
273
|
+
object.$renamed = true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
transform(object: Node, parents: Node[]) {
|
|
278
|
+
var matchType = object.type === "Identifier" ? "Identifier" : "Context";
|
|
279
|
+
if (matchType === "Identifier") {
|
|
280
|
+
this.transformIdentifier(object, parents);
|
|
281
|
+
} else {
|
|
282
|
+
this.transformContext(object, parents);
|
|
283
|
+
}
|
|
213
284
|
}
|
|
214
285
|
}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { ok } from "assert";
|
|
2
2
|
import { reservedIdentifiers } from "../../constants";
|
|
3
|
-
import { walk } from "../../traverse";
|
|
4
3
|
import { isValidIdentifier } from "../../util/compare";
|
|
5
4
|
import { Node } from "../../util/gen";
|
|
6
5
|
import { getIdentifierInfo } from "../../util/identifiers";
|
|
7
6
|
import {
|
|
8
|
-
getDefiningContext,
|
|
9
|
-
getVarContext,
|
|
10
|
-
getLexContext,
|
|
11
|
-
isContext,
|
|
12
7
|
getReferencingContexts,
|
|
13
8
|
getAllDefiningContexts,
|
|
14
9
|
} from "../../util/insert";
|
|
@@ -30,11 +25,13 @@ export default class VariableAnalysis extends Transform {
|
|
|
30
25
|
|
|
31
26
|
/**
|
|
32
27
|
* Set of global identifiers to never be redefined
|
|
28
|
+
*
|
|
29
|
+
* - Used to not accidentally block access to a global variable
|
|
33
30
|
*/
|
|
34
31
|
globals: Set<string>;
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
|
-
* Set of
|
|
34
|
+
* Set of identifiers that are defined within the program
|
|
38
35
|
*/
|
|
39
36
|
notGlobals: Set<string>;
|
|
40
37
|
|
|
@@ -48,77 +45,73 @@ export default class VariableAnalysis extends Transform {
|
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
match(object, parents) {
|
|
51
|
-
return
|
|
48
|
+
return object.type === "Identifier";
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
transform(object, parents) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
transform(object: Node, parents: Node[]) {
|
|
52
|
+
var name = object.name;
|
|
53
|
+
ok(typeof name === "string");
|
|
54
|
+
if (!isValidIdentifier(name)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (reservedIdentifiers.has(name)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (this.options.globalVariables.has(name)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var info = getIdentifierInfo(object, parents);
|
|
66
|
+
if (!info.spec.isReferenced) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (info.spec.isExported) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
var isDefined = info.spec.isDefined;
|
|
75
|
+
|
|
76
|
+
// Keep track of defined names within the program
|
|
77
|
+
if (isDefined) {
|
|
78
|
+
this.notGlobals.add(object.name);
|
|
79
|
+
this.globals.delete(object.name);
|
|
80
|
+
} else if (!this.notGlobals.has(object.name)) {
|
|
81
|
+
this.globals.add(object.name);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
var definingContexts = info.spec.isDefined
|
|
85
|
+
? getAllDefiningContexts(object, parents)
|
|
86
|
+
: getReferencingContexts(object, parents, info);
|
|
87
|
+
|
|
88
|
+
ok(definingContexts.length);
|
|
89
|
+
|
|
90
|
+
definingContexts.forEach((definingContext) => {
|
|
91
|
+
// ok(
|
|
92
|
+
// isContext(definingContext),
|
|
93
|
+
// `${definingContext.type} is not a context`
|
|
94
|
+
// );
|
|
95
|
+
|
|
96
|
+
if (isDefined) {
|
|
97
|
+
// Add to defined Map
|
|
98
|
+
if (!this.defined.has(definingContext)) {
|
|
99
|
+
this.defined.set(definingContext, new Set());
|
|
61
100
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (info.spec.isExported) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
var isDefined = info.spec.isDefined;
|
|
80
|
-
|
|
81
|
-
// Keep track of defined names within the program
|
|
82
|
-
if (isDefined) {
|
|
83
|
-
this.notGlobals.add(o.name);
|
|
84
|
-
this.globals.delete(o.name);
|
|
85
|
-
} else if (!this.notGlobals.has(o.name)) {
|
|
86
|
-
this.globals.add(o.name);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
var definingContexts = info.spec.isDefined
|
|
90
|
-
? getAllDefiningContexts(o, p)
|
|
91
|
-
: getReferencingContexts(o, p, info);
|
|
92
|
-
|
|
93
|
-
ok(definingContexts.length);
|
|
94
|
-
|
|
95
|
-
definingContexts.forEach((definingContext) => {
|
|
96
|
-
// ok(
|
|
97
|
-
// isContext(definingContext),
|
|
98
|
-
// `${definingContext.type} is not a context`
|
|
99
|
-
// );
|
|
100
|
-
|
|
101
|
-
if (isDefined) {
|
|
102
|
-
// Add to defined Map
|
|
103
|
-
if (!this.defined.has(definingContext)) {
|
|
104
|
-
this.defined.set(definingContext, new Set());
|
|
105
|
-
}
|
|
106
|
-
this.defined.get(definingContext).add(name);
|
|
107
|
-
this.references.has(definingContext) &&
|
|
108
|
-
this.references.get(definingContext).delete(name);
|
|
109
|
-
} else {
|
|
110
|
-
// Add to references Map
|
|
111
|
-
if (
|
|
112
|
-
!this.defined.has(definingContext) ||
|
|
113
|
-
!this.defined.get(definingContext).has(name)
|
|
114
|
-
) {
|
|
115
|
-
if (!this.references.has(definingContext)) {
|
|
116
|
-
this.references.set(definingContext, new Set());
|
|
117
|
-
}
|
|
118
|
-
this.references.get(definingContext).add(name);
|
|
119
|
-
}
|
|
101
|
+
this.defined.get(definingContext).add(name);
|
|
102
|
+
this.references.has(definingContext) &&
|
|
103
|
+
this.references.get(definingContext).delete(name);
|
|
104
|
+
} else {
|
|
105
|
+
// Add to references Map
|
|
106
|
+
if (
|
|
107
|
+
!this.defined.has(definingContext) ||
|
|
108
|
+
!this.defined.get(definingContext).has(name)
|
|
109
|
+
) {
|
|
110
|
+
if (!this.references.has(definingContext)) {
|
|
111
|
+
this.references.set(definingContext, new Set());
|
|
120
112
|
}
|
|
121
|
-
|
|
113
|
+
this.references.get(definingContext).add(name);
|
|
114
|
+
}
|
|
122
115
|
}
|
|
123
116
|
});
|
|
124
117
|
}
|
|
@@ -219,9 +219,7 @@ export default class Lock extends Transform {
|
|
|
219
219
|
if (this.options.lock.domainLock && this.options.lock.domainLock.length) {
|
|
220
220
|
choices.push("domainLock");
|
|
221
221
|
}
|
|
222
|
-
|
|
223
|
-
choices.push("nativeFunction");
|
|
224
|
-
}
|
|
222
|
+
|
|
225
223
|
if (this.options.lock.context && this.options.lock.context.length) {
|
|
226
224
|
choices.push("context");
|
|
227
225
|
}
|
|
@@ -312,45 +310,6 @@ export default class Lock extends Transform {
|
|
|
312
310
|
|
|
313
311
|
break;
|
|
314
312
|
|
|
315
|
-
case "nativeFunction":
|
|
316
|
-
var set = this.options.lock.nativeFunctions;
|
|
317
|
-
if (set === true) {
|
|
318
|
-
if (this.options.target == "node") {
|
|
319
|
-
set = new Set(["Function", "String"]);
|
|
320
|
-
} else {
|
|
321
|
-
set = new Set(["Function", "String", "fetch"]);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
if (Array.isArray(set)) {
|
|
325
|
-
set = new Set(set);
|
|
326
|
-
}
|
|
327
|
-
if (!set) {
|
|
328
|
-
set = new Set();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
var fn = choice(Array.from(set));
|
|
332
|
-
if (fn) {
|
|
333
|
-
test = Template(
|
|
334
|
-
`(${fn}+"").indexOf("[native code]") == -1`
|
|
335
|
-
).single().expression;
|
|
336
|
-
|
|
337
|
-
if (Math.random() > 0.5) {
|
|
338
|
-
test = Template(
|
|
339
|
-
`${fn}.toString().split("{ [native code] }").length <= 1`
|
|
340
|
-
).single().expression;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
nodes.push(
|
|
344
|
-
IfStatement(
|
|
345
|
-
test,
|
|
346
|
-
this.getCounterMeasuresCode(object, parents) || [],
|
|
347
|
-
null
|
|
348
|
-
)
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
break;
|
|
353
|
-
|
|
354
313
|
case "startDate":
|
|
355
314
|
test = BinaryExpression(
|
|
356
315
|
"<",
|