webfuscator 1.3.2 → 1.3.4
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/README.md +4 -1
- package/dist/obfuscator.d.ts.map +1 -1
- package/dist/obfuscator.js +29 -19
- package/dist/obfuscator.js.map +1 -1
- package/dist/options.d.ts +10 -11
- package/dist/options.d.ts.map +1 -1
- package/dist/transforms/arguments-to-parameters.d.ts +2 -5
- package/dist/transforms/arguments-to-parameters.d.ts.map +1 -1
- package/dist/transforms/arguments-to-parameters.js +2 -5
- package/dist/transforms/arguments-to-parameters.js.map +1 -1
- package/dist/transforms/arrow-to-function.d.ts +3 -4
- package/dist/transforms/arrow-to-function.d.ts.map +1 -1
- package/dist/transforms/arrow-to-function.js +3 -4
- package/dist/transforms/arrow-to-function.js.map +1 -1
- package/dist/transforms/collapse-single-use-temps.d.ts +2 -3
- package/dist/transforms/collapse-single-use-temps.d.ts.map +1 -1
- package/dist/transforms/collapse-single-use-temps.js +2 -3
- package/dist/transforms/collapse-single-use-temps.js.map +1 -1
- package/dist/transforms/conceal-strings.d.ts +8 -25
- package/dist/transforms/conceal-strings.d.ts.map +1 -1
- package/dist/transforms/conceal-strings.js +33 -48
- package/dist/transforms/conceal-strings.js.map +1 -1
- package/dist/transforms/const-let-to-var.d.ts +3 -4
- package/dist/transforms/const-let-to-var.d.ts.map +1 -1
- package/dist/transforms/const-let-to-var.js +3 -4
- package/dist/transforms/const-let-to-var.js.map +1 -1
- package/dist/transforms/do-while-to-while.d.ts +2 -3
- package/dist/transforms/do-while-to-while.d.ts.map +1 -1
- package/dist/transforms/do-while-to-while.js +2 -3
- package/dist/transforms/do-while-to-while.js.map +1 -1
- package/dist/transforms/drop-console.d.ts +1 -4
- package/dist/transforms/drop-console.d.ts.map +1 -1
- package/dist/transforms/drop-console.js +1 -4
- package/dist/transforms/drop-console.js.map +1 -1
- package/dist/transforms/expand-binary-assignment.d.ts +2 -8
- package/dist/transforms/expand-binary-assignment.d.ts.map +1 -1
- package/dist/transforms/expand-binary-assignment.js +2 -8
- package/dist/transforms/expand-binary-assignment.js.map +1 -1
- package/dist/transforms/expand-logical-assignment.d.ts +3 -2
- package/dist/transforms/expand-logical-assignment.d.ts.map +1 -1
- package/dist/transforms/expand-logical-assignment.js +3 -2
- package/dist/transforms/expand-logical-assignment.js.map +1 -1
- package/dist/transforms/extract-object-properties.d.ts +2 -3
- package/dist/transforms/extract-object-properties.d.ts.map +1 -1
- package/dist/transforms/extract-object-properties.js +2 -3
- package/dist/transforms/extract-object-properties.js.map +1 -1
- package/dist/transforms/fold-builtin-methods.d.ts +2 -3
- package/dist/transforms/fold-builtin-methods.d.ts.map +1 -1
- package/dist/transforms/fold-builtin-methods.js +2 -3
- package/dist/transforms/fold-builtin-methods.js.map +1 -1
- package/dist/transforms/fold-constants.d.ts +2 -2
- package/dist/transforms/fold-constants.js +2 -2
- package/dist/transforms/for-to-while.d.ts +2 -3
- package/dist/transforms/for-to-while.d.ts.map +1 -1
- package/dist/transforms/for-to-while.js +2 -3
- package/dist/transforms/for-to-while.js.map +1 -1
- package/dist/transforms/function-declaration-to-expression.d.ts +3 -7
- package/dist/transforms/function-declaration-to-expression.d.ts.map +1 -1
- package/dist/transforms/function-declaration-to-expression.js +3 -7
- package/dist/transforms/function-declaration-to-expression.js.map +1 -1
- package/dist/transforms/hoist-variables.d.ts +2 -4
- package/dist/transforms/hoist-variables.d.ts.map +1 -1
- package/dist/transforms/hoist-variables.js +2 -4
- package/dist/transforms/hoist-variables.js.map +1 -1
- package/dist/transforms/inline-functions.d.ts +2 -2
- package/dist/transforms/inline-functions.js +2 -2
- package/dist/transforms/logical-to-ternary.d.ts +2 -2
- package/dist/transforms/logical-to-ternary.js +2 -2
- package/dist/transforms/mangle-properties.d.ts +2 -3
- package/dist/transforms/mangle-properties.d.ts.map +1 -1
- package/dist/transforms/mangle-properties.js +2 -3
- package/dist/transforms/mangle-properties.js.map +1 -1
- package/dist/transforms/nullish-coalescing-to-ternary.d.ts +2 -2
- package/dist/transforms/nullish-coalescing-to-ternary.js +2 -2
- package/dist/transforms/numbers-to-strings.d.ts +1 -5
- package/dist/transforms/numbers-to-strings.d.ts.map +1 -1
- package/dist/transforms/numbers-to-strings.js +1 -5
- package/dist/transforms/numbers-to-strings.js.map +1 -1
- package/dist/transforms/object-method-to-property.d.ts +2 -10
- package/dist/transforms/object-method-to-property.d.ts.map +1 -1
- package/dist/transforms/object-method-to-property.js +2 -10
- package/dist/transforms/object-method-to-property.js.map +1 -1
- package/dist/transforms/optional-chaining-to-ternary.d.ts +2 -3
- package/dist/transforms/optional-chaining-to-ternary.d.ts.map +1 -1
- package/dist/transforms/optional-chaining-to-ternary.js +2 -3
- package/dist/transforms/optional-chaining-to-ternary.js.map +1 -1
- package/dist/transforms/pack-declarations-into-parameters.d.ts +2 -5
- package/dist/transforms/pack-declarations-into-parameters.d.ts.map +1 -1
- package/dist/transforms/pack-declarations-into-parameters.js +2 -5
- package/dist/transforms/pack-declarations-into-parameters.js.map +1 -1
- package/dist/transforms/pack-expressions.d.ts +25 -0
- package/dist/transforms/pack-expressions.d.ts.map +1 -0
- package/dist/transforms/pack-expressions.js +187 -0
- package/dist/transforms/pack-expressions.js.map +1 -0
- package/dist/transforms/pack.d.ts +2 -4
- package/dist/transforms/pack.d.ts.map +1 -1
- package/dist/transforms/pack.js +2 -4
- package/dist/transforms/pack.js.map +1 -1
- package/dist/transforms/remove-unreachable-code.d.ts +2 -4
- package/dist/transforms/remove-unreachable-code.d.ts.map +1 -1
- package/dist/transforms/remove-unreachable-code.js +2 -4
- package/dist/transforms/remove-unreachable-code.js.map +1 -1
- package/dist/transforms/remove-unused-code.d.ts +2 -2
- package/dist/transforms/remove-unused-code.js +2 -2
- package/dist/transforms/rename-identifiers.d.ts +2 -3
- package/dist/transforms/rename-identifiers.d.ts.map +1 -1
- package/dist/transforms/rename-identifiers.js +2 -3
- package/dist/transforms/rename-identifiers.js.map +1 -1
- package/dist/transforms/reorder-function-declarations.d.ts +2 -6
- package/dist/transforms/reorder-function-declarations.d.ts.map +1 -1
- package/dist/transforms/reorder-function-declarations.js +2 -6
- package/dist/transforms/reorder-function-declarations.js.map +1 -1
- package/dist/transforms/specials-to-strings.d.ts +2 -13
- package/dist/transforms/specials-to-strings.d.ts.map +1 -1
- package/dist/transforms/specials-to-strings.js +2 -13
- package/dist/transforms/specials-to-strings.js.map +1 -1
- package/dist/transforms/switch-to-if.d.ts +3 -4
- package/dist/transforms/switch-to-if.d.ts.map +1 -1
- package/dist/transforms/switch-to-if.js +3 -4
- package/dist/transforms/switch-to-if.js.map +1 -1
- package/dist/transforms/ternary-to-if.d.ts +2 -3
- package/dist/transforms/ternary-to-if.d.ts.map +1 -1
- package/dist/transforms/ternary-to-if.js +2 -3
- package/dist/transforms/ternary-to-if.js.map +1 -1
- package/dist/transforms/update-to-assignment.d.ts +2 -6
- package/dist/transforms/update-to-assignment.d.ts.map +1 -1
- package/dist/transforms/update-to-assignment.js +2 -6
- package/dist/transforms/update-to-assignment.js.map +1 -1
- package/dist/transforms/yodify-conditions.d.ts +2 -3
- package/dist/transforms/yodify-conditions.d.ts.map +1 -1
- package/dist/transforms/yodify-conditions.js +2 -3
- package/dist/transforms/yodify-conditions.js.map +1 -1
- package/package.json +1 -1
- package/src/obfuscator.ts +31 -19
- package/src/options.ts +12 -13
- package/src/transforms/arguments-to-parameters.ts +2 -5
- package/src/transforms/arrow-to-function.ts +3 -4
- package/src/transforms/collapse-single-use-temps.ts +2 -3
- package/src/transforms/conceal-strings.ts +48 -48
- package/src/transforms/const-let-to-var.ts +3 -4
- package/src/transforms/do-while-to-while.ts +2 -3
- package/src/transforms/drop-console.ts +1 -4
- package/src/transforms/expand-binary-assignment.ts +2 -8
- package/src/transforms/expand-logical-assignment.ts +3 -2
- package/src/transforms/extract-object-properties.ts +2 -3
- package/src/transforms/fold-builtin-methods.ts +2 -3
- package/src/transforms/fold-constants.ts +2 -2
- package/src/transforms/for-to-while.ts +2 -3
- package/src/transforms/function-declaration-to-expression.ts +3 -7
- package/src/transforms/hoist-variables.ts +2 -4
- package/src/transforms/inline-functions.ts +2 -2
- package/src/transforms/logical-to-ternary.ts +2 -2
- package/src/transforms/mangle-properties.ts +2 -3
- package/src/transforms/nullish-coalescing-to-ternary.ts +2 -2
- package/src/transforms/numbers-to-strings.ts +1 -5
- package/src/transforms/object-method-to-property.ts +2 -10
- package/src/transforms/optional-chaining-to-ternary.ts +2 -3
- package/src/transforms/pack-declarations-into-parameters.ts +2 -5
- package/src/transforms/pack-expressions.ts +237 -0
- package/src/transforms/pack.ts +2 -4
- package/src/transforms/remove-unreachable-code.ts +2 -4
- package/src/transforms/remove-unused-code.ts +2 -2
- package/src/transforms/rename-identifiers.ts +2 -3
- package/src/transforms/reorder-function-declarations.ts +2 -6
- package/src/transforms/specials-to-strings.ts +2 -13
- package/src/transforms/switch-to-if.ts +3 -4
- package/src/transforms/ternary-to-if.ts +2 -3
- package/src/transforms/update-to-assignment.ts +2 -6
- package/src/transforms/yodify-conditions.ts +2 -3
- package/dist/transforms/merge-variable-declarations.d.ts +0 -17
- package/dist/transforms/merge-variable-declarations.d.ts.map +0 -1
- package/dist/transforms/merge-variable-declarations.js +0 -68
- package/dist/transforms/merge-variable-declarations.js.map +0 -1
- package/src/transforms/merge-variable-declarations.ts +0 -91
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yodify-conditions.js","sourceRoot":"","sources":["../../src/transforms/yodify-conditions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AAGjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD
|
|
1
|
+
{"version":3,"file":"yodify-conditions.js","sourceRoot":"","sources":["../../src/transforms/yodify-conditions.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/obfuscator.ts
CHANGED
|
@@ -31,13 +31,13 @@ import { hoistVariables } from './transforms/hoist-variables'
|
|
|
31
31
|
import { inlineFunctions } from './transforms/inline-functions'
|
|
32
32
|
import { logicalToTernary } from './transforms/logical-to-ternary'
|
|
33
33
|
import { mangleProperties } from './transforms/mangle-properties'
|
|
34
|
-
import { mergeVariableDeclarations } from './transforms/merge-variable-declarations'
|
|
35
34
|
import { nullishCoalescingToTernary } from './transforms/nullish-coalescing-to-ternary'
|
|
36
35
|
import { numbersToStrings } from './transforms/numbers-to-strings'
|
|
37
36
|
import { objectMethodToProperty } from './transforms/object-method-to-property'
|
|
38
37
|
import { optionalChainingToTernary } from './transforms/optional-chaining-to-ternary'
|
|
39
38
|
import { pack } from './transforms/pack'
|
|
40
39
|
import { packDeclarationsIntoParameters } from './transforms/pack-declarations-into-parameters'
|
|
40
|
+
import { packExpressions } from './transforms/pack-expressions'
|
|
41
41
|
import { removeAnonymousFunctionNames } from './transforms/remove-anonymous-function-names'
|
|
42
42
|
import { removeUnreachableCode } from './transforms/remove-unreachable-code'
|
|
43
43
|
import { removeUnusedCode } from './transforms/remove-unused-code'
|
|
@@ -125,16 +125,15 @@ const LOWERING: readonly ConfigurablePhase[] = [
|
|
|
125
125
|
['ternaryToIf', ternaryToIf],
|
|
126
126
|
]
|
|
127
127
|
|
|
128
|
-
// `packDeclarationsIntoParameters` must precede declaration motion
|
|
128
|
+
// `packDeclarationsIntoParameters` must precede declaration motion.
|
|
129
129
|
// `reorderFunctionDeclarations` follows `functionDeclarationToExpression`, so it
|
|
130
|
-
// moves only declarations still needed for hoisting. `
|
|
131
|
-
//
|
|
132
|
-
//
|
|
130
|
+
// moves only declarations still needed for hoisting. `numbersToStrings` follows
|
|
131
|
+
// the fixed point, yodification, and `specialsToStrings` because they need or
|
|
132
|
+
// create numbers.
|
|
133
133
|
const POST_PROCESS: readonly ConfigurablePhase[] = [
|
|
134
134
|
['packDeclarationsIntoParameters', packDeclarationsIntoParameters],
|
|
135
135
|
['reorderFunctionDeclarations', reorderFunctionDeclarations],
|
|
136
136
|
['hoistVariables', hoistVariables],
|
|
137
|
-
['mergeVariableDeclarations', mergeVariableDeclarations],
|
|
138
137
|
['yodifyConditions', yodifyConditions],
|
|
139
138
|
['specialsToStrings', specialsToStrings],
|
|
140
139
|
['numbersToStrings', numbersToStrings],
|
|
@@ -144,12 +143,17 @@ const POST_PROCESS: readonly ConfigurablePhase[] = [
|
|
|
144
143
|
// generated vault bindings use the caller's name generator.
|
|
145
144
|
const PROTECTION: readonly ConfigurablePhase[] = [['concealStrings', concealStrings]]
|
|
146
145
|
|
|
147
|
-
//
|
|
146
|
+
// All binding-producing passes run before renaming so their generated
|
|
147
|
+
// identifiers also receive names from the configured string generator.
|
|
148
148
|
const RENAME: readonly ConfigurablePhase[] = [['renameIdentifiers', renameIdentifiers]]
|
|
149
149
|
|
|
150
|
+
// Statement packing consumes final declaration and expression shapes and creates
|
|
151
|
+
// no bindings, so it runs after renaming and before whole-program packing.
|
|
152
|
+
const FINAL_SHAPE: readonly ConfigurablePhase[] = [['packExpressions', packExpressions]]
|
|
153
|
+
|
|
150
154
|
// Packing serializes the finished program to a string and rebuilds it through
|
|
151
155
|
// the Function constructor. It must see final names and shapes, so it runs after
|
|
152
|
-
// every other rewrite
|
|
156
|
+
// every other rewrite.
|
|
153
157
|
const PACK: readonly ConfigurablePhase[] = [['pack', pack]]
|
|
154
158
|
|
|
155
159
|
// Tests derive their all-transforms setup from this list. The phase tables remain
|
|
@@ -162,6 +166,7 @@ export const CONFIGURABLE_TRANSFORM_NAMES: readonly TransformName[] = [
|
|
|
162
166
|
...POST_PROCESS,
|
|
163
167
|
...PROTECTION,
|
|
164
168
|
...RENAME,
|
|
169
|
+
...FINAL_SHAPE,
|
|
165
170
|
...PACK,
|
|
166
171
|
].map(([name]) => name)
|
|
167
172
|
|
|
@@ -175,7 +180,7 @@ export function obfuscate(code: string, options: ObfuscatorOptions = {}): string
|
|
|
175
180
|
const ast = run(log, 'parse', () => parse(code, parserOptions))
|
|
176
181
|
|
|
177
182
|
for (const [name, fn] of BEFORE_PREPARATION) {
|
|
178
|
-
if (!
|
|
183
|
+
if (!shouldRun(name, options)) {
|
|
179
184
|
continue
|
|
180
185
|
}
|
|
181
186
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
@@ -186,7 +191,7 @@ export function obfuscate(code: string, options: ObfuscatorOptions = {}): string
|
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
for (const [name, fn] of PRE_LOOP) {
|
|
189
|
-
if (!
|
|
194
|
+
if (!shouldRun(name, options)) {
|
|
190
195
|
continue
|
|
191
196
|
}
|
|
192
197
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
@@ -195,35 +200,42 @@ export function obfuscate(code: string, options: ObfuscatorOptions = {}): string
|
|
|
195
200
|
runFixedPoint(ast, options, baseCtx, log)
|
|
196
201
|
|
|
197
202
|
for (const [name, fn] of LOWERING) {
|
|
198
|
-
if (!
|
|
203
|
+
if (!shouldRun(name, options)) {
|
|
199
204
|
continue
|
|
200
205
|
}
|
|
201
206
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
for (const [name, fn] of POST_PROCESS) {
|
|
205
|
-
if (!
|
|
210
|
+
if (!shouldRun(name, options)) {
|
|
206
211
|
continue
|
|
207
212
|
}
|
|
208
213
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
209
214
|
}
|
|
210
215
|
|
|
211
216
|
for (const [name, fn] of PROTECTION) {
|
|
212
|
-
if (!
|
|
217
|
+
if (!shouldRun(name, options)) {
|
|
213
218
|
continue
|
|
214
219
|
}
|
|
215
220
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
216
221
|
}
|
|
217
222
|
|
|
218
223
|
for (const [name, fn] of RENAME) {
|
|
219
|
-
if (!
|
|
224
|
+
if (!shouldRun(name, options)) {
|
|
225
|
+
continue
|
|
226
|
+
}
|
|
227
|
+
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
for (const [name, fn] of FINAL_SHAPE) {
|
|
231
|
+
if (!shouldRun(name, options)) {
|
|
220
232
|
continue
|
|
221
233
|
}
|
|
222
234
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
223
235
|
}
|
|
224
236
|
|
|
225
237
|
for (const [name, fn] of PACK) {
|
|
226
|
-
if (!
|
|
238
|
+
if (!shouldRun(name, options)) {
|
|
227
239
|
continue
|
|
228
240
|
}
|
|
229
241
|
run(log, name, () => fn(ast, ctxFor(name, options, baseCtx)))
|
|
@@ -242,7 +254,7 @@ export function obfuscate(code: string, options: ObfuscatorOptions = {}): string
|
|
|
242
254
|
)
|
|
243
255
|
}
|
|
244
256
|
|
|
245
|
-
function
|
|
257
|
+
function shouldRun(name: TransformName, options: ObfuscatorOptions): boolean {
|
|
246
258
|
const entry = options.transforms?.[name]
|
|
247
259
|
return entry !== undefined && entry !== false
|
|
248
260
|
}
|
|
@@ -277,14 +289,14 @@ function runFixedPoint(
|
|
|
277
289
|
ctx: TransformContext,
|
|
278
290
|
log: Logger | null,
|
|
279
291
|
): void {
|
|
280
|
-
const
|
|
281
|
-
if (
|
|
292
|
+
const transforms = FIXED_POINT.filter(([name]) => shouldRun(name, options))
|
|
293
|
+
if (transforms.length === 0) {
|
|
282
294
|
return
|
|
283
295
|
}
|
|
284
296
|
|
|
285
297
|
for (let iter = 0; iter < FIXED_POINT_ITERATION_CAP; iter++) {
|
|
286
298
|
let any = false
|
|
287
|
-
for (const [name, fn] of
|
|
299
|
+
for (const [name, fn] of transforms) {
|
|
288
300
|
if (run(log, name, () => fn(ast, ctx))) {
|
|
289
301
|
any = true
|
|
290
302
|
}
|
package/src/options.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { StringGeneratorModeOption } from './utils/string-generator'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Exported transform entry points. Preparation passes
|
|
5
|
-
*
|
|
4
|
+
* Exported transform entry points. Preparation passes always run and do not
|
|
5
|
+
* appear here.
|
|
6
6
|
*/
|
|
7
7
|
export type TransformName =
|
|
8
8
|
| 'dropConsole'
|
|
@@ -23,7 +23,6 @@ export type TransformName =
|
|
|
23
23
|
| 'functionDeclarationToExpression'
|
|
24
24
|
| 'reorderFunctionDeclarations'
|
|
25
25
|
| 'hoistVariables'
|
|
26
|
-
| 'mergeVariableDeclarations'
|
|
27
26
|
| 'switchToIf'
|
|
28
27
|
| 'forToWhile'
|
|
29
28
|
| 'doWhileToWhile'
|
|
@@ -41,9 +40,10 @@ export type TransformName =
|
|
|
41
40
|
| 'concealStrings'
|
|
42
41
|
| 'mangleProperties'
|
|
43
42
|
| 'renameIdentifiers'
|
|
43
|
+
| 'packExpressions'
|
|
44
44
|
| 'pack'
|
|
45
45
|
|
|
46
|
-
// An
|
|
46
|
+
// An options object runs the transform and replaces its string-generator mode.
|
|
47
47
|
type TransformEntry = boolean | { stringGeneratorMode?: StringGeneratorModeOption }
|
|
48
48
|
|
|
49
49
|
/** Maps a zero-based ordinal to a stable property name. */
|
|
@@ -105,8 +105,6 @@ export interface ConcealStringsOptions {
|
|
|
105
105
|
cache?: boolean
|
|
106
106
|
/** Choose how much of the UTF-16 range pads each pool. Default `'regional'`. */
|
|
107
107
|
cover?: 'full' | 'regional' | 'used'
|
|
108
|
-
/** Reuse one vault entry for equal strings. Default `true`. */
|
|
109
|
-
deduplicate?: boolean
|
|
110
108
|
/** Use one program vault or a separate vault per function. Default `'program'`. */
|
|
111
109
|
scope?: 'function' | 'program'
|
|
112
110
|
}
|
|
@@ -130,21 +128,22 @@ export interface ObfuscatorOptions {
|
|
|
130
128
|
/** Logs each pipeline step and its elapsed milliseconds to stderr. */
|
|
131
129
|
verbose?: boolean
|
|
132
130
|
/**
|
|
133
|
-
* Per-transform
|
|
134
|
-
*
|
|
131
|
+
* Per-transform entries and string-generator overrides. An omitted key or
|
|
132
|
+
* `false` means that transform does not run. Preparation passes always run.
|
|
135
133
|
*/
|
|
136
134
|
transforms?: TransformsMap
|
|
137
135
|
/**
|
|
138
|
-
*
|
|
139
|
-
* array mixes modes uniformly. Individual transforms may
|
|
140
|
-
* `transforms.<name>.stringGeneratorMode`. Default
|
|
136
|
+
* Mode used by transforms that run for generated identifiers, labels, and
|
|
137
|
+
* string contents. An array mixes modes uniformly. Individual transforms may
|
|
138
|
+
* override it through `transforms.<name>.stringGeneratorMode`. Default
|
|
139
|
+
* `'mangled'`.
|
|
141
140
|
*/
|
|
142
141
|
stringGeneratorMode?: StringGeneratorModeOption
|
|
143
|
-
/** Seed
|
|
142
|
+
/** Seed used by randomized transforms that run. Same seed, same output. Default `0`. */
|
|
144
143
|
seed?: number
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
// Resolved per-call
|
|
146
|
+
// Resolved per-call settings handed to each executed pass.
|
|
148
147
|
export interface TransformContext {
|
|
149
148
|
concealStrings?: ConcealStringsOptions
|
|
150
149
|
mangleProperties?: ManglePropertiesOptions
|
|
@@ -8,11 +8,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
8
8
|
import { isInStrictContext } from '../utils/paths'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Replaces numeric `arguments[i]` reads with the corresponding
|
|
12
|
-
* sloppy functions with simple parameter lists.
|
|
13
|
-
* that index is written or its parameter is reassigned. Reassigning, deleting,
|
|
14
|
-
* or passing around `arguments` disables the rewrite. Missing parameters are
|
|
15
|
-
* never added because that would change `fn.length`.
|
|
11
|
+
* Replaces eligible numeric `arguments[i]` reads with the corresponding
|
|
12
|
+
* parameter in sloppy functions with simple parameter lists.
|
|
16
13
|
*
|
|
17
14
|
* @example
|
|
18
15
|
* // ◀️ before
|
|
@@ -6,10 +6,9 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Converts
|
|
10
|
-
* Arrows that use `super`
|
|
11
|
-
*
|
|
12
|
-
* function can be constructed with `new` and has a `prototype`.
|
|
9
|
+
* Converts eligible arrow functions to function expressions while preserving
|
|
10
|
+
* their lexical captures. Arrows that use `super` or whose values escape stay
|
|
11
|
+
* unchanged.
|
|
13
12
|
*
|
|
14
13
|
* @example
|
|
15
14
|
* // ◀️ before
|
|
@@ -15,9 +15,8 @@ import { valueToLiteral } from '../utils/literal'
|
|
|
15
15
|
import { isCalleeOrTagOf } from '../utils/paths'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* another.
|
|
18
|
+
* Replaces eligible single-use temporary bindings with their values and removes
|
|
19
|
+
* the declarations.
|
|
21
20
|
*
|
|
22
21
|
* @example
|
|
23
22
|
* // ◀️ before
|
|
@@ -11,25 +11,8 @@ import { mulberry32, shuffleInPlace } from '../utils/random'
|
|
|
11
11
|
const RECORD_WIDTH = 4
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Replaces runtime string literals with calls to a generated decoder
|
|
15
|
-
*
|
|
16
|
-
* surrogates without relying on mutable built-ins. The default `regional` pool
|
|
17
|
-
* covers U+0000-00FF and every 256-unit page used by the program. `full` covers
|
|
18
|
-
* all 65,536 code units.
|
|
19
|
-
*
|
|
20
|
-
* `scope: 'program'` creates one vault. `scope: 'function'` creates a vault per
|
|
21
|
-
* function but repeats the program-wide pool in each one. Parameter defaults and
|
|
22
|
-
* computed keys use the enclosing vault because they run before the function
|
|
23
|
-
* body.
|
|
24
|
-
*
|
|
25
|
-
* Directives, module specifiers, import attributes, and non-computed keys are not
|
|
26
|
-
* runtime expressions, so they stay unchanged.
|
|
27
|
-
*
|
|
28
|
-
* This is obfuscation, not encryption. The output contains the decoder and all
|
|
29
|
-
* data needed to recover each string. `cover: 'used'` also leaves one-unit
|
|
30
|
-
* strings in the pool and may reproduce longer text by chance.
|
|
31
|
-
*
|
|
32
|
-
* The example uses `{ cover: 'used' }` to keep the pool short.
|
|
14
|
+
* Replaces runtime string literals with calls to a generated decoder backed by
|
|
15
|
+
* an obfuscated string vault.
|
|
33
16
|
*
|
|
34
17
|
* @example
|
|
35
18
|
* // ◀️ before
|
|
@@ -38,21 +21,21 @@ const RECORD_WIDTH = 4
|
|
|
38
21
|
* }
|
|
39
22
|
*
|
|
40
23
|
* // ▶️ after
|
|
41
|
-
*
|
|
42
|
-
*
|
|
24
|
+
* var _stringPool = " lo,He";
|
|
25
|
+
* var _stringPayload = [0, 4, 7, 2, 2, 6, 2],
|
|
43
26
|
* _stringMetadata = [0, 7, 4, 5],
|
|
44
27
|
* _stringCache = [null],
|
|
45
28
|
* _stringDecoder = function (_entry) {
|
|
46
|
-
*
|
|
29
|
+
* var _cached = _stringCache[_entry];
|
|
47
30
|
* if (_cached !== null) return _cached;
|
|
48
|
-
*
|
|
31
|
+
* var _result = "",
|
|
49
32
|
* _record = _entry * 4,
|
|
50
33
|
* _start = _stringMetadata[_record],
|
|
51
34
|
* _length = _stringMetadata[_record + 1],
|
|
52
35
|
* _stringKey = _stringMetadata[_record + 2],
|
|
53
36
|
* _stringStep = _stringMetadata[_record + 3];
|
|
54
|
-
* for (
|
|
55
|
-
*
|
|
37
|
+
* for (var _position = 0; _position < _length; _position++) {
|
|
38
|
+
* var _stringMask = _stringKey + _position * _stringStep & 7;
|
|
56
39
|
* _result += _stringPool[_stringPayload[_start + _position] ^ _stringMask];
|
|
57
40
|
* }
|
|
58
41
|
* _stringCache[_entry] = _result;
|
|
@@ -65,7 +48,7 @@ const RECORD_WIDTH = 4
|
|
|
65
48
|
export function concealStrings(ast: File, ctx: TransformContext): boolean {
|
|
66
49
|
const options = resolveOptions(ctx.concealStrings)
|
|
67
50
|
const rng = mulberry32(ctx.seed)
|
|
68
|
-
const state: State = { changed: false, groups: new Map(), options }
|
|
51
|
+
const state: State = { changed: false, groups: new Map(), options, program: null }
|
|
69
52
|
|
|
70
53
|
if (options.scope === 'function') {
|
|
71
54
|
normalizeConciseArrows(ast, options)
|
|
@@ -76,17 +59,18 @@ export function concealStrings(ast: File, ctx: TransformContext): boolean {
|
|
|
76
59
|
return false
|
|
77
60
|
}
|
|
78
61
|
const pool = buildSharedPool(state.groups.values(), options.cover, rng)
|
|
62
|
+
const poolIdentifier = t.identifier(state.program!.scope.generateUid('stringPool'))
|
|
79
63
|
for (const group of state.groups.values()) {
|
|
80
|
-
concealGroup(group, options, pool, rng)
|
|
64
|
+
concealGroup(group, options, pool, poolIdentifier, rng)
|
|
81
65
|
state.changed = true
|
|
82
66
|
}
|
|
67
|
+
insertSharedPool(state.program!, poolIdentifier, pool.value)
|
|
83
68
|
return state.changed
|
|
84
69
|
}
|
|
85
70
|
|
|
86
71
|
interface ResolvedOptions {
|
|
87
72
|
cache: boolean
|
|
88
73
|
cover: 'full' | 'regional' | 'used'
|
|
89
|
-
deduplicate: boolean
|
|
90
74
|
scope: 'function' | 'program'
|
|
91
75
|
}
|
|
92
76
|
|
|
@@ -106,6 +90,7 @@ interface VaultGroup {
|
|
|
106
90
|
interface State extends ChangeState {
|
|
107
91
|
groups: Map<VaultOwner, VaultGroup>
|
|
108
92
|
options: ResolvedOptions
|
|
93
|
+
program: NodePath<t.Program> | null
|
|
109
94
|
}
|
|
110
95
|
|
|
111
96
|
interface Entry {
|
|
@@ -117,7 +102,6 @@ interface VaultData {
|
|
|
117
102
|
indexMask: number
|
|
118
103
|
metadata: number[]
|
|
119
104
|
payload: number[]
|
|
120
|
-
pool: string
|
|
121
105
|
}
|
|
122
106
|
|
|
123
107
|
interface SharedPool {
|
|
@@ -135,6 +119,9 @@ interface VaultIdentifiers {
|
|
|
135
119
|
}
|
|
136
120
|
|
|
137
121
|
const collectVisitor: Visitor<State> = {
|
|
122
|
+
Program(path, state) {
|
|
123
|
+
state.program = path
|
|
124
|
+
},
|
|
138
125
|
StringLiteral(path, state) {
|
|
139
126
|
if (!isRuntimeString(path)) {
|
|
140
127
|
return
|
|
@@ -155,7 +142,6 @@ const collectVisitor: Visitor<State> = {
|
|
|
155
142
|
function resolveOptions(options: ConcealStringsOptions | undefined): ResolvedOptions {
|
|
156
143
|
const cache = options?.cache ?? true
|
|
157
144
|
const cover = options?.cover ?? 'regional'
|
|
158
|
-
const deduplicate = options?.deduplicate ?? true
|
|
159
145
|
const scope = options?.scope ?? 'program'
|
|
160
146
|
if (typeof cache !== 'boolean') {
|
|
161
147
|
throw new TypeError('concealStrings cache must be a boolean')
|
|
@@ -163,13 +149,10 @@ function resolveOptions(options: ConcealStringsOptions | undefined): ResolvedOpt
|
|
|
163
149
|
if (cover !== 'full' && cover !== 'regional' && cover !== 'used') {
|
|
164
150
|
throw new TypeError("concealStrings cover must be 'full', 'regional', or 'used'")
|
|
165
151
|
}
|
|
166
|
-
if (typeof deduplicate !== 'boolean') {
|
|
167
|
-
throw new TypeError('concealStrings deduplicate must be a boolean')
|
|
168
|
-
}
|
|
169
152
|
if (scope !== 'function' && scope !== 'program') {
|
|
170
153
|
throw new TypeError("concealStrings scope must be 'function' or 'program'")
|
|
171
154
|
}
|
|
172
|
-
return { cache, cover,
|
|
155
|
+
return { cache, cover, scope }
|
|
173
156
|
}
|
|
174
157
|
|
|
175
158
|
function normalizeConciseArrows(ast: File, options: ResolvedOptions): void {
|
|
@@ -237,12 +220,19 @@ function concealGroup(
|
|
|
237
220
|
group: VaultGroup,
|
|
238
221
|
options: ResolvedOptions,
|
|
239
222
|
pool: SharedPool,
|
|
223
|
+
poolIdentifier: t.Identifier,
|
|
240
224
|
rng: () => number,
|
|
241
225
|
): void {
|
|
242
|
-
const entries = makeEntries(group.occurrences
|
|
226
|
+
const entries = makeEntries(group.occurrences)
|
|
243
227
|
shuffleInPlace(entries, rng)
|
|
244
228
|
const data = encodeEntries(entries, pool, rng)
|
|
245
|
-
const identifiers = insertVault(
|
|
229
|
+
const identifiers = insertVault(
|
|
230
|
+
statementBody(group.owner),
|
|
231
|
+
entries.length,
|
|
232
|
+
data,
|
|
233
|
+
options.cache,
|
|
234
|
+
poolIdentifier,
|
|
235
|
+
)
|
|
246
236
|
|
|
247
237
|
for (let index = 0; index < entries.length; index++) {
|
|
248
238
|
for (const occurrence of entries[index]!.occurrences) {
|
|
@@ -254,10 +244,7 @@ function concealGroup(
|
|
|
254
244
|
}
|
|
255
245
|
}
|
|
256
246
|
|
|
257
|
-
function makeEntries(occurrences: Occurrence[]
|
|
258
|
-
if (!deduplicate) {
|
|
259
|
-
return occurrences.map((occurrence) => ({ occurrences: [occurrence], value: occurrence.value }))
|
|
260
|
-
}
|
|
247
|
+
function makeEntries(occurrences: Occurrence[]): Entry[] {
|
|
261
248
|
const byValue = new Map<string, Entry>()
|
|
262
249
|
for (const occurrence of occurrences) {
|
|
263
250
|
let entry = byValue.get(occurrence.value)
|
|
@@ -308,7 +295,7 @@ function encodeEntries(entries: Entry[], pool: SharedPool, rng: () => number): V
|
|
|
308
295
|
payload.push(truePosition ^ maskPosition(position, key, step, pool.indexMask))
|
|
309
296
|
}
|
|
310
297
|
}
|
|
311
|
-
return { indexMask: pool.indexMask, metadata, payload
|
|
298
|
+
return { indexMask: pool.indexMask, metadata, payload }
|
|
312
299
|
}
|
|
313
300
|
|
|
314
301
|
function makePoolUnits(usedUnits: ReadonlySet<string>, cover: ResolvedOptions['cover']): string[] {
|
|
@@ -385,6 +372,7 @@ function insertVault(
|
|
|
385
372
|
entryCount: number,
|
|
386
373
|
data: VaultData,
|
|
387
374
|
cache: boolean,
|
|
375
|
+
pool: t.Identifier,
|
|
388
376
|
): VaultIdentifiers {
|
|
389
377
|
const fresh = (purpose: string): t.Identifier => t.identifier(body.scope.generateUid(purpose))
|
|
390
378
|
const identifiers: VaultIdentifiers = {
|
|
@@ -392,11 +380,10 @@ function insertVault(
|
|
|
392
380
|
decoder: fresh('stringDecoder'),
|
|
393
381
|
metadata: fresh('stringMetadata'),
|
|
394
382
|
payload: fresh('stringPayload'),
|
|
395
|
-
pool
|
|
383
|
+
pool,
|
|
396
384
|
}
|
|
397
385
|
const decoder = t.functionExpression(null, [], t.blockStatement([]))
|
|
398
386
|
const declarations = [
|
|
399
|
-
t.variableDeclarator(identifiers.pool, t.stringLiteral(data.pool)),
|
|
400
387
|
t.variableDeclarator(identifiers.payload, numericArray(data.payload)),
|
|
401
388
|
t.variableDeclarator(identifiers.metadata, numericArray(data.metadata)),
|
|
402
389
|
]
|
|
@@ -410,7 +397,7 @@ function insertVault(
|
|
|
410
397
|
}
|
|
411
398
|
declarations.push(t.variableDeclarator(identifiers.decoder, decoder))
|
|
412
399
|
|
|
413
|
-
const declaration = t.variableDeclaration('
|
|
400
|
+
const declaration = t.variableDeclaration('var', declarations)
|
|
414
401
|
const [declarationPath] = body.unshiftContainer('body', declaration)
|
|
415
402
|
const declaratorPaths = declarationPath!.get('declarations') as NodePath<t.VariableDeclarator>[]
|
|
416
403
|
const decoderPath = declaratorPaths
|
|
@@ -420,6 +407,19 @@ function insertVault(
|
|
|
420
407
|
return identifiers
|
|
421
408
|
}
|
|
422
409
|
|
|
410
|
+
function insertSharedPool(
|
|
411
|
+
program: NodePath<t.Program>,
|
|
412
|
+
identifier: t.Identifier,
|
|
413
|
+
value: string,
|
|
414
|
+
): void {
|
|
415
|
+
program.unshiftContainer(
|
|
416
|
+
'body',
|
|
417
|
+
t.variableDeclaration('var', [
|
|
418
|
+
t.variableDeclarator(t.cloneNode(identifier), t.stringLiteral(value)),
|
|
419
|
+
]),
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
423
|
function populateDecoder(
|
|
424
424
|
decoderPath: NodePath<t.FunctionExpression>,
|
|
425
425
|
vault: VaultIdentifiers,
|
|
@@ -441,13 +441,13 @@ function populateDecoder(
|
|
|
441
441
|
if (vault.cache) {
|
|
442
442
|
const cached = fresh('cached')
|
|
443
443
|
statements.push(
|
|
444
|
-
t.variableDeclaration('
|
|
444
|
+
t.variableDeclaration('var', [t.variableDeclarator(cached, indexed(vault.cache, entry))]),
|
|
445
445
|
t.ifStatement(t.binaryExpression('!==', cached, t.nullLiteral()), t.returnStatement(cached)),
|
|
446
446
|
)
|
|
447
447
|
}
|
|
448
448
|
|
|
449
449
|
statements.push(
|
|
450
|
-
t.variableDeclaration('
|
|
450
|
+
t.variableDeclaration('var', [
|
|
451
451
|
t.variableDeclarator(result, t.stringLiteral('')),
|
|
452
452
|
t.variableDeclarator(record, t.binaryExpression('*', entry, t.numericLiteral(RECORD_WIDTH))),
|
|
453
453
|
t.variableDeclarator(start, indexed(vault.metadata, record)),
|
|
@@ -465,11 +465,11 @@ function populateDecoder(
|
|
|
465
465
|
),
|
|
466
466
|
]),
|
|
467
467
|
t.forStatement(
|
|
468
|
-
t.variableDeclaration('
|
|
468
|
+
t.variableDeclaration('var', [t.variableDeclarator(position, t.numericLiteral(0))]),
|
|
469
469
|
t.binaryExpression('<', position, length),
|
|
470
470
|
t.updateExpression('++', position),
|
|
471
471
|
t.blockStatement([
|
|
472
|
-
t.variableDeclaration('
|
|
472
|
+
t.variableDeclaration('var', [
|
|
473
473
|
t.variableDeclarator(mask, maskExpression(position, key, step, indexMask)),
|
|
474
474
|
]),
|
|
475
475
|
t.expressionStatement(
|
|
@@ -4,10 +4,9 @@ import * as t from '@babel/types'
|
|
|
4
4
|
import type { File } from '@babel/types'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Converts `let` and `const` declarations to `var
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* iteration's value.
|
|
7
|
+
* Converts eligible `let` and `const` declarations to `var`, renaming bindings
|
|
8
|
+
* when needed to avoid hoisting conflicts. Loop bindings stay unchanged when
|
|
9
|
+
* conversion would alter iteration behavior.
|
|
11
10
|
*
|
|
12
11
|
* @example
|
|
13
12
|
* // ◀️ before
|
|
@@ -7,9 +7,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
7
7
|
import { collectLoopLabels, generateLoopLabel, redirectContinues } from '../utils/loop-lowering'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Rewrites `do` loops as `while
|
|
11
|
-
*
|
|
12
|
-
* The inner label is omitted when nothing uses it.
|
|
10
|
+
* Rewrites `do...while` loops as equivalent `while` loops while preserving
|
|
11
|
+
* `continue` behavior.
|
|
13
12
|
*
|
|
14
13
|
* @example
|
|
15
14
|
* // ◀️ before
|
|
@@ -8,10 +8,7 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
8
8
|
import type { ChangeState } from '../utils/change-tracking'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Removes `console
|
|
12
|
-
* locally shadowed. Matches dot, bracket, and optional-chain forms.
|
|
13
|
-
* Leaves indirect uses alone (`console.log.call(...)`, assignments,
|
|
14
|
-
* `await console.log(...)`).
|
|
11
|
+
* Removes eligible `console` call expression statements.
|
|
15
12
|
*
|
|
16
13
|
* @example
|
|
17
14
|
* // ◀️ before
|
|
@@ -6,14 +6,8 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Member objects and computed keys are cached so the read and write use the same
|
|
13
|
-
* evaluated receiver. The cache assignment stays on the outer write target,
|
|
14
|
-
* which evaluates before its right side.
|
|
15
|
-
*
|
|
16
|
-
* Compound and expanded forms use the same operator semantics, including BigInt.
|
|
9
|
+
* Expands arithmetic and bitwise compound assignments into simple assignments
|
|
10
|
+
* while preserving single evaluation of member receivers and computed keys.
|
|
17
11
|
*
|
|
18
12
|
* @example
|
|
19
13
|
* // ◀️ before
|
|
@@ -6,8 +6,9 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Expands logical compound assignments into equivalent short-circuiting
|
|
10
|
+
* assignments while preserving single evaluation of member receivers and
|
|
11
|
+
* computed keys.
|
|
11
12
|
*
|
|
12
13
|
* @example
|
|
13
14
|
* // ◀️ before
|
|
@@ -9,9 +9,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
9
9
|
import { isCalleeOrTagOf } from '../utils/paths'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Replaces
|
|
13
|
-
*
|
|
14
|
-
* values directly.
|
|
12
|
+
* Replaces eligible object and array wrapper bindings with separate bindings
|
|
13
|
+
* for their statically accessed entries.
|
|
15
14
|
*
|
|
16
15
|
* @example
|
|
17
16
|
* // ◀️ before
|
|
@@ -10,9 +10,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
10
10
|
import { valueToLiteral } from '../utils/literal'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Replaces built-in calls and reads with smaller
|
|
14
|
-
*
|
|
15
|
-
* names, optional forms, and regexp methods stay unchanged.
|
|
13
|
+
* Replaces eligible built-in calls and property reads with smaller equivalent
|
|
14
|
+
* expressions or constants.
|
|
16
15
|
*
|
|
17
16
|
* @example
|
|
18
17
|
* // ◀️ before
|
|
@@ -10,8 +10,8 @@ import { valueToLiteral } from '../utils/literal'
|
|
|
10
10
|
import { isCalleeOrTagOf } from '../utils/paths'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Replaces pure compile-time constant expressions with equivalent literals or
|
|
14
|
+
* selected branches.
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* // ◀️ before
|