js-confuser 2.0.0-alpha.5 → 2.0.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/.github/ISSUE_TEMPLATE/bug_report.md +43 -43
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/.github/workflows/node.js.yml +28 -28
- package/.prettierrc +4 -4
- package/CHANGELOG.md +1015 -989
- package/CODE_OF_CONDUCT.md +131 -131
- package/CONTRIBUTING.md +52 -52
- package/LICENSE +21 -21
- package/Migration.md +72 -71
- package/README.md +86 -78
- package/dist/constants.js +43 -43
- package/dist/index.js +14 -23
- package/dist/obfuscator.js +31 -25
- package/dist/order.js +4 -4
- package/dist/presets.js +31 -31
- package/dist/templates/integrityTemplate.js +4 -4
- package/dist/templates/template.js +1 -2
- package/dist/transforms/astScrambler.js +1 -2
- package/dist/transforms/calculator.js +1 -2
- package/dist/transforms/controlFlowFlattening.js +93 -63
- package/dist/transforms/deadCode.js +1 -2
- package/dist/transforms/dispatcher.js +4 -5
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +1 -2
- package/dist/transforms/extraction/objectExtraction.js +1 -2
- package/dist/transforms/finalizer.js +1 -2
- package/dist/transforms/flatten.js +1 -2
- package/dist/transforms/identifier/globalConcealing.js +15 -2
- package/dist/transforms/identifier/movedDeclarations.js +8 -7
- package/dist/transforms/identifier/renameVariables.js +7 -7
- package/dist/transforms/lock/integrity.js +11 -10
- package/dist/transforms/lock/lock.js +2 -3
- package/dist/transforms/minify.js +11 -29
- package/dist/transforms/opaquePredicates.js +1 -2
- package/dist/transforms/pack.js +5 -2
- package/dist/transforms/plugin.js +18 -19
- package/dist/transforms/preparation.js +16 -16
- package/dist/transforms/renameLabels.js +1 -2
- package/dist/transforms/rgf.js +8 -9
- package/dist/transforms/shuffle.js +1 -2
- package/dist/transforms/string/encoding.js +1 -2
- package/dist/transforms/string/stringCompression.js +3 -4
- package/dist/transforms/string/stringConcealing.js +8 -3
- package/dist/transforms/string/stringEncoding.js +1 -2
- package/dist/transforms/variableMasking.js +1 -2
- package/dist/utils/NameGen.js +2 -2
- package/dist/utils/PredicateGen.js +1 -2
- package/dist/utils/ast-utils.js +87 -88
- package/dist/utils/function-utils.js +8 -8
- package/dist/utils/node.js +5 -6
- package/dist/utils/object-utils.js +4 -4
- package/dist/utils/random-utils.js +20 -20
- package/dist/utils/static-utils.js +1 -2
- package/dist/validateOptions.js +4 -7
- package/index.d.ts +17 -17
- package/package.json +61 -59
- package/src/constants.ts +168 -168
- package/src/index.ts +118 -118
- package/src/obfuscationResult.ts +49 -49
- package/src/obfuscator.ts +501 -497
- package/src/options.ts +407 -407
- package/src/order.ts +54 -54
- package/src/presets.ts +125 -125
- package/src/templates/bufferToStringTemplate.ts +57 -57
- package/src/templates/deadCodeTemplates.ts +1185 -1185
- package/src/templates/getGlobalTemplate.ts +76 -76
- package/src/templates/integrityTemplate.ts +64 -64
- package/src/templates/setFunctionLengthTemplate.ts +11 -11
- package/src/templates/stringCompressionTemplate.ts +20 -20
- package/src/templates/tamperProtectionTemplates.ts +120 -120
- package/src/templates/template.ts +224 -224
- package/src/transforms/astScrambler.ts +99 -99
- package/src/transforms/calculator.ts +99 -99
- package/src/transforms/controlFlowFlattening.ts +1716 -1664
- package/src/transforms/deadCode.ts +82 -82
- package/src/transforms/dispatcher.ts +450 -450
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +156 -158
- package/src/transforms/extraction/objectExtraction.ts +186 -186
- package/src/transforms/finalizer.ts +74 -74
- package/src/transforms/flatten.ts +421 -420
- package/src/transforms/identifier/globalConcealing.ts +315 -295
- package/src/transforms/identifier/movedDeclarations.ts +252 -251
- package/src/transforms/identifier/renameVariables.ts +328 -321
- package/src/transforms/lock/integrity.ts +117 -114
- package/src/transforms/lock/lock.ts +418 -425
- package/src/transforms/minify.ts +615 -629
- package/src/transforms/opaquePredicates.ts +100 -100
- package/src/transforms/pack.ts +239 -231
- package/src/transforms/plugin.ts +173 -173
- package/src/transforms/preparation.ts +349 -347
- package/src/transforms/renameLabels.ts +175 -175
- package/src/transforms/rgf.ts +322 -322
- package/src/transforms/shuffle.ts +82 -82
- package/src/transforms/string/encoding.ts +144 -144
- package/src/transforms/string/stringCompression.ts +128 -128
- package/src/transforms/string/stringConcealing.ts +312 -298
- package/src/transforms/string/stringEncoding.ts +80 -80
- package/src/transforms/string/stringSplitting.ts +77 -77
- package/src/transforms/variableMasking.ts +257 -257
- package/src/utils/IntGen.ts +33 -33
- package/src/utils/NameGen.ts +116 -116
- package/src/utils/PredicateGen.ts +61 -61
- package/src/utils/ast-utils.ts +663 -663
- package/src/utils/function-utils.ts +50 -50
- package/src/utils/gen-utils.ts +48 -48
- package/src/utils/node.ts +78 -78
- package/src/utils/object-utils.ts +21 -21
- package/src/utils/random-utils.ts +93 -93
- package/src/utils/static-utils.ts +66 -66
- package/src/validateOptions.ts +256 -259
- package/tsconfig.json +13 -14
- package/dist/probability.js +0 -1
- package/dist/transforms/functionOutlining.js +0 -230
- package/dist/utils/ControlObject.js +0 -125
|
@@ -1,298 +1,312 @@
|
|
|
1
|
-
import * as t from "@babel/types";
|
|
2
|
-
import { NodePath } from "@babel/traverse";
|
|
3
|
-
import Template from "../../templates/template";
|
|
4
|
-
import { PluginArg, PluginObject } from "../plugin";
|
|
5
|
-
import { Order } from "../../order";
|
|
6
|
-
import { ok } from "assert";
|
|
7
|
-
import { BufferToStringTemplate } from "../../templates/bufferToStringTemplate";
|
|
8
|
-
import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
|
|
9
|
-
import {
|
|
10
|
-
ensureComputedExpression,
|
|
11
|
-
isModuleImport,
|
|
12
|
-
prepend,
|
|
13
|
-
prependProgram,
|
|
14
|
-
} from "../../utils/ast-utils";
|
|
15
|
-
import {
|
|
16
|
-
chance,
|
|
17
|
-
choice,
|
|
18
|
-
getRandomInteger,
|
|
19
|
-
getRandomString,
|
|
20
|
-
} from "../../utils/random-utils";
|
|
21
|
-
import { CustomStringEncoding } from "../../options";
|
|
22
|
-
import { createDefaultStringEncoding } from "./encoding";
|
|
23
|
-
import { numericLiteral } from "../../utils/node";
|
|
24
|
-
import { NO_REMOVE } from "../../constants";
|
|
25
|
-
|
|
26
|
-
interface StringConcealingInterface {
|
|
27
|
-
encodingImplementation: CustomStringEncoding;
|
|
28
|
-
fnName: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const STRING_CONCEALING = Symbol("StringConcealing");
|
|
32
|
-
|
|
33
|
-
interface NodeStringConcealing {
|
|
34
|
-
[STRING_CONCEALING]?: StringConcealingInterface;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
38
|
-
const me = Plugin(Order.StringConcealing, {
|
|
39
|
-
changeData: {
|
|
40
|
-
strings: 0,
|
|
41
|
-
decryptionFunctions: 0,
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const blocks: NodePath<t.Block>[] = [];
|
|
46
|
-
const stringMap = new Map<string, number>();
|
|
47
|
-
const stringArrayName = me.getPlaceholder() + "_array";
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
var
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
typeof
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
encoding
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
block
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
stringMap.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
t.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
};
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { NodePath } from "@babel/traverse";
|
|
3
|
+
import Template from "../../templates/template";
|
|
4
|
+
import { PluginArg, PluginObject } from "../plugin";
|
|
5
|
+
import { Order } from "../../order";
|
|
6
|
+
import { ok } from "assert";
|
|
7
|
+
import { BufferToStringTemplate } from "../../templates/bufferToStringTemplate";
|
|
8
|
+
import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
|
|
9
|
+
import {
|
|
10
|
+
ensureComputedExpression,
|
|
11
|
+
isModuleImport,
|
|
12
|
+
prepend,
|
|
13
|
+
prependProgram,
|
|
14
|
+
} from "../../utils/ast-utils";
|
|
15
|
+
import {
|
|
16
|
+
chance,
|
|
17
|
+
choice,
|
|
18
|
+
getRandomInteger,
|
|
19
|
+
getRandomString,
|
|
20
|
+
} from "../../utils/random-utils";
|
|
21
|
+
import { CustomStringEncoding } from "../../options";
|
|
22
|
+
import { createDefaultStringEncoding } from "./encoding";
|
|
23
|
+
import { numericLiteral } from "../../utils/node";
|
|
24
|
+
import { NO_REMOVE } from "../../constants";
|
|
25
|
+
|
|
26
|
+
interface StringConcealingInterface {
|
|
27
|
+
encodingImplementation: CustomStringEncoding;
|
|
28
|
+
fnName: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const STRING_CONCEALING = Symbol("StringConcealing");
|
|
32
|
+
|
|
33
|
+
interface NodeStringConcealing {
|
|
34
|
+
[STRING_CONCEALING]?: StringConcealingInterface;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
38
|
+
const me = Plugin(Order.StringConcealing, {
|
|
39
|
+
changeData: {
|
|
40
|
+
strings: 0,
|
|
41
|
+
decryptionFunctions: 0,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const blocks: NodePath<t.Block>[] = [];
|
|
46
|
+
const stringMap = new Map<string, number>();
|
|
47
|
+
const stringArrayName = me.getPlaceholder() + "_array";
|
|
48
|
+
const stringArrayCacheName = me.getPlaceholder() + "_cache";
|
|
49
|
+
|
|
50
|
+
let encodingImplementations: { [identity: string]: CustomStringEncoding } =
|
|
51
|
+
Object.create(null);
|
|
52
|
+
|
|
53
|
+
let availableStringEncodings = me.options.customStringEncodings;
|
|
54
|
+
|
|
55
|
+
// If no custom encodings are provided, use the default encoding
|
|
56
|
+
if (!availableStringEncodings || availableStringEncodings.length === 0) {
|
|
57
|
+
availableStringEncodings = [createDefaultStringEncoding];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function hasAllEncodings() {
|
|
61
|
+
return availableStringEncodings.length === 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createStringEncoding(): CustomStringEncoding {
|
|
65
|
+
var encodingIndex = getRandomInteger(0, availableStringEncodings.length);
|
|
66
|
+
var encoding = availableStringEncodings[encodingIndex];
|
|
67
|
+
|
|
68
|
+
if (typeof encoding === "function") {
|
|
69
|
+
encoding = encoding(encodingImplementations);
|
|
70
|
+
|
|
71
|
+
var duplicateIdentity =
|
|
72
|
+
typeof encoding.identity !== "undefined" &&
|
|
73
|
+
typeof encodingImplementations[encoding.identity] !== "undefined";
|
|
74
|
+
|
|
75
|
+
if (duplicateIdentity || encoding === null) {
|
|
76
|
+
// Null returned -> All encodings have been created
|
|
77
|
+
// Duplicate identity -> Most likely all encodings have been created
|
|
78
|
+
|
|
79
|
+
// No longer create new encodings using this function
|
|
80
|
+
availableStringEncodings = availableStringEncodings.filter(
|
|
81
|
+
(x) => x !== encoding
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Return a random encoding already made
|
|
85
|
+
encoding = choice(Object.values(encodingImplementations));
|
|
86
|
+
ok(encoding, "Failed to create main string encoding");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (typeof encoding.identity === "undefined") {
|
|
91
|
+
encoding.identity = encodingIndex.toString();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (typeof encoding.code === "string") {
|
|
95
|
+
encoding.code = new Template(encoding.code);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
me.changeData.decryptionFunctions++;
|
|
99
|
+
encodingImplementations[encoding.identity] = encoding;
|
|
100
|
+
|
|
101
|
+
return encoding;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
visitor: {
|
|
106
|
+
Program: {
|
|
107
|
+
exit(programPath: NodePath<t.Program>) {
|
|
108
|
+
let mainEncodingImplementation: CustomStringEncoding;
|
|
109
|
+
|
|
110
|
+
// Create a main encoder function for the Program
|
|
111
|
+
(programPath.node as NodeStringConcealing)[STRING_CONCEALING] = {
|
|
112
|
+
encodingImplementation: (mainEncodingImplementation =
|
|
113
|
+
createStringEncoding()),
|
|
114
|
+
fnName: me.getPlaceholder() + "_MAIN_STR",
|
|
115
|
+
};
|
|
116
|
+
blocks.push(programPath);
|
|
117
|
+
|
|
118
|
+
// Use that encoder function for these fake strings
|
|
119
|
+
const fakeStringCount = getRandomInteger(75, 125);
|
|
120
|
+
for (var i = 0; i < fakeStringCount; i++) {
|
|
121
|
+
const fakeString = getRandomString(getRandomInteger(5, 50));
|
|
122
|
+
stringMap.set(
|
|
123
|
+
mainEncodingImplementation.encode(fakeString),
|
|
124
|
+
stringMap.size
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
programPath.traverse({
|
|
129
|
+
StringLiteral: {
|
|
130
|
+
exit(path: NodePath<t.StringLiteral>) {
|
|
131
|
+
const originalValue = path.node.value;
|
|
132
|
+
|
|
133
|
+
// Ignore require() calls / Import statements
|
|
134
|
+
if (isModuleImport(path)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Minimum length of 3 characters
|
|
139
|
+
if (originalValue.length < 3) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Check user setting
|
|
144
|
+
if (
|
|
145
|
+
!me.computeProbabilityMap(
|
|
146
|
+
me.options.stringConcealing,
|
|
147
|
+
originalValue
|
|
148
|
+
)
|
|
149
|
+
) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let block = path.findParent(
|
|
154
|
+
(p) =>
|
|
155
|
+
p.isBlock() &&
|
|
156
|
+
!!(p.node as NodeStringConcealing)?.[STRING_CONCEALING]
|
|
157
|
+
) as NodePath<t.Block>;
|
|
158
|
+
|
|
159
|
+
let stringConcealingInterface = (
|
|
160
|
+
block?.node as NodeStringConcealing
|
|
161
|
+
)?.[STRING_CONCEALING] as StringConcealingInterface;
|
|
162
|
+
|
|
163
|
+
if (
|
|
164
|
+
!block ||
|
|
165
|
+
(!hasAllEncodings() && chance(75 - blocks.length))
|
|
166
|
+
) {
|
|
167
|
+
// Create a new encoder function
|
|
168
|
+
// Select random block parent (or Program)
|
|
169
|
+
block = path.findParent((p) =>
|
|
170
|
+
p.isBlock()
|
|
171
|
+
) as NodePath<t.Block>;
|
|
172
|
+
|
|
173
|
+
const stringConcealingNode =
|
|
174
|
+
block.node as NodeStringConcealing;
|
|
175
|
+
|
|
176
|
+
// Ensure not to overwrite the previous encoders
|
|
177
|
+
if (!stringConcealingNode[STRING_CONCEALING]) {
|
|
178
|
+
// Create a new encoding function for this block
|
|
179
|
+
const encodingImplementation = createStringEncoding();
|
|
180
|
+
const fnName =
|
|
181
|
+
me.getPlaceholder() + "_STR_" + blocks.length;
|
|
182
|
+
|
|
183
|
+
stringConcealingInterface = {
|
|
184
|
+
encodingImplementation,
|
|
185
|
+
fnName: fnName,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Save this info in the AST for future strings
|
|
189
|
+
stringConcealingNode[STRING_CONCEALING] =
|
|
190
|
+
stringConcealingInterface;
|
|
191
|
+
|
|
192
|
+
blocks.push(block);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
ok(stringConcealingInterface);
|
|
197
|
+
|
|
198
|
+
const encodedValue =
|
|
199
|
+
stringConcealingInterface.encodingImplementation.encode(
|
|
200
|
+
originalValue
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// If a decoder function is provided, use it to validate each encoded string
|
|
204
|
+
if (
|
|
205
|
+
typeof stringConcealingInterface.encodingImplementation
|
|
206
|
+
.decode === "function"
|
|
207
|
+
) {
|
|
208
|
+
const decodedValue =
|
|
209
|
+
stringConcealingInterface.encodingImplementation.decode(
|
|
210
|
+
encodedValue
|
|
211
|
+
);
|
|
212
|
+
if (decodedValue !== originalValue) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let index = stringMap.get(encodedValue);
|
|
218
|
+
|
|
219
|
+
if (typeof index === "undefined") {
|
|
220
|
+
index = stringMap.size;
|
|
221
|
+
stringMap.set(encodedValue, index);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
me.changeData.strings++;
|
|
225
|
+
|
|
226
|
+
// Ensure the string is computed so we can replace it with complex call expression
|
|
227
|
+
ensureComputedExpression(path);
|
|
228
|
+
|
|
229
|
+
// Replace the string literal with a call to the decoder function
|
|
230
|
+
path.replaceWith(
|
|
231
|
+
t.callExpression(
|
|
232
|
+
t.identifier(stringConcealingInterface.fnName),
|
|
233
|
+
[numericLiteral(index)]
|
|
234
|
+
)
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
// Skip the transformation for the newly created node
|
|
238
|
+
path.skip();
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const bufferToStringName = me.getPlaceholder() + "_bufferToString";
|
|
244
|
+
const getGlobalFnName = me.getPlaceholder() + "_getGlobal";
|
|
245
|
+
|
|
246
|
+
const bufferToStringCode = BufferToStringTemplate.compile({
|
|
247
|
+
GetGlobalTemplate: createGetGlobalTemplate(me, programPath),
|
|
248
|
+
getGlobalFnName: getGlobalFnName,
|
|
249
|
+
BufferToString: bufferToStringName,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
prependProgram(programPath, bufferToStringCode);
|
|
253
|
+
|
|
254
|
+
// Create the string array
|
|
255
|
+
prependProgram(
|
|
256
|
+
programPath,
|
|
257
|
+
t.variableDeclaration("var", [
|
|
258
|
+
t.variableDeclarator(
|
|
259
|
+
t.identifier(stringArrayName),
|
|
260
|
+
t.arrayExpression(
|
|
261
|
+
Array.from(stringMap.keys()).map((x) => t.stringLiteral(x))
|
|
262
|
+
)
|
|
263
|
+
),
|
|
264
|
+
])
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// Create the string cache
|
|
268
|
+
prependProgram(
|
|
269
|
+
programPath,
|
|
270
|
+
new Template(`
|
|
271
|
+
var {stringArrayCacheName} = {};
|
|
272
|
+
`).single({
|
|
273
|
+
stringArrayCacheName,
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
for (var block of blocks) {
|
|
278
|
+
const { encodingImplementation, fnName } = (
|
|
279
|
+
block.node as NodeStringConcealing
|
|
280
|
+
)[STRING_CONCEALING] as StringConcealingInterface;
|
|
281
|
+
|
|
282
|
+
const decodeFnName = fnName + "_decode";
|
|
283
|
+
|
|
284
|
+
ok(encodingImplementation.code instanceof Template);
|
|
285
|
+
|
|
286
|
+
// The decoder function
|
|
287
|
+
const decoder = encodingImplementation.code
|
|
288
|
+
.addSymbols(NO_REMOVE)
|
|
289
|
+
.compile({
|
|
290
|
+
fnName: decodeFnName,
|
|
291
|
+
__bufferToStringFunction__: bufferToStringName,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// The main function to get the string value
|
|
295
|
+
const retrieveFunctionDeclaration = new Template(`
|
|
296
|
+
function ${fnName}(index) {
|
|
297
|
+
if (typeof ${stringArrayCacheName}[index] === 'undefined') {
|
|
298
|
+
return ${stringArrayCacheName}[index] = ${decodeFnName}(${stringArrayName}[index]);
|
|
299
|
+
}
|
|
300
|
+
return ${stringArrayCacheName}[index];
|
|
301
|
+
}
|
|
302
|
+
`)
|
|
303
|
+
.addSymbols(NO_REMOVE)
|
|
304
|
+
.single<t.FunctionDeclaration>();
|
|
305
|
+
|
|
306
|
+
prepend(block, [...decoder, retrieveFunctionDeclaration]);
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
};
|