webfuscator 1.3.2 → 1.3.3
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 +25 -13
- package/dist/obfuscator.js.map +1 -1
- package/dist/options.d.ts +10 -9
- 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 +2 -19
- package/dist/transforms/conceal-strings.d.ts.map +1 -1
- package/dist/transforms/conceal-strings.js +2 -19
- 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/merge-variable-declarations.d.ts +1 -3
- package/dist/transforms/merge-variable-declarations.d.ts.map +1 -1
- package/dist/transforms/merge-variable-declarations.js +1 -3
- package/dist/transforms/merge-variable-declarations.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 +20 -0
- package/dist/transforms/pack-expressions.d.ts.map +1 -0
- package/dist/transforms/pack-expressions.js +132 -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 +27 -13
- package/src/options.ts +12 -10
- 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 +2 -19
- 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/merge-variable-declarations.ts +1 -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 +159 -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
|
@@ -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
|
|
@@ -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 classic `for` loops as
|
|
11
|
-
*
|
|
12
|
-
* stay unchanged.
|
|
10
|
+
* Rewrites classic `for` loops as equivalent `while` loops. `for...in` and
|
|
11
|
+
* `for...of` loops stay unchanged.
|
|
13
12
|
*
|
|
14
13
|
* @example
|
|
15
14
|
* // ◀️ before
|
|
@@ -6,13 +6,9 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Rewrites function declarations
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Name inference and recursive references still use the `var` binding.
|
|
14
|
-
*
|
|
15
|
-
* Block-level and module top-level declarations stay unchanged.
|
|
9
|
+
* Rewrites eligible function declarations in scripts and function bodies as
|
|
10
|
+
* `var`-initialized function expressions. Declarations stay unchanged when
|
|
11
|
+
* moving initialization to their statement position could alter execution.
|
|
16
12
|
*
|
|
17
13
|
* @example
|
|
18
14
|
* // ◀️ before
|
|
@@ -6,10 +6,8 @@ import type { File } from '@babel/types'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Moves `var` declarations to the
|
|
10
|
-
* initializer evaluation.
|
|
11
|
-
*
|
|
12
|
-
* Direct exports stay in place. Static blocks keep separate declarations.
|
|
9
|
+
* Moves `var` declarations to the beginning of their containing function or
|
|
10
|
+
* program without moving initializer evaluation.
|
|
13
11
|
*
|
|
14
12
|
* @example
|
|
15
13
|
* // ◀️ before
|
|
@@ -12,8 +12,8 @@ import { generateLoopLabel } from '../utils/loop-lowering'
|
|
|
12
12
|
import { isInStrictContext } from '../utils/paths'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Replaces eligible calls with
|
|
16
|
-
*
|
|
15
|
+
* Replaces eligible function calls with the called function's body and removes
|
|
16
|
+
* declarations that become unused.
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* // ◀️ before
|
|
@@ -9,8 +9,8 @@ import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
|
9
9
|
import { buildNonNullishCheck, buildNullishCheck } from '../utils/nullish'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Rewrites logical expressions as
|
|
13
|
-
*
|
|
12
|
+
* Rewrites logical expressions as equivalent conditional expressions or
|
|
13
|
+
* guarded assignments while preserving short-circuit evaluation.
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* // ◀️ before
|
|
@@ -12,9 +12,8 @@ import { mulberry32 } from '../utils/random'
|
|
|
12
12
|
import { StringGenerator } from '../utils/string-generator'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Renames statically known public properties
|
|
16
|
-
*
|
|
17
|
-
* property distinct from the generated names.
|
|
15
|
+
* Renames statically known public properties using one consistent program-wide
|
|
16
|
+
* mapping.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
20
19
|
* // ◀️ before
|
|
@@ -4,9 +4,7 @@ import type { File } from '@babel/types'
|
|
|
4
4
|
import { rewriteStatementLists } from '../utils/statement-lists'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Merges adjacent variable declarations
|
|
8
|
-
* match. It runs in programs, blocks, switch cases, and static blocks, and
|
|
9
|
-
* removes unlabeled empty statements between compatible declarations.
|
|
7
|
+
* Merges adjacent compatible variable declarations into a single declaration.
|
|
10
8
|
*
|
|
11
9
|
* @example
|
|
12
10
|
* // ◀️ before
|
|
@@ -8,8 +8,8 @@ import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
|
8
8
|
import { buildNonNullishCheck, buildNullishCheck } from '../utils/nullish'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Rewrites
|
|
12
|
-
*
|
|
11
|
+
* Rewrites nullish-coalescing expressions as equivalent conditional expressions
|
|
12
|
+
* while evaluating the left operand once.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* // ◀️ before
|
|
@@ -7,11 +7,7 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
7
7
|
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Rewrites numeric literals as
|
|
11
|
-
* or `~`, the existing operator supplies that coercion. Other unary operators
|
|
12
|
-
* keep the wrapper because their string behavior differs.
|
|
13
|
-
*
|
|
14
|
-
* Preparation has already converted numeric object keys to strings.
|
|
10
|
+
* Rewrites numeric literals as equivalent string-coercion expressions.
|
|
15
11
|
*
|
|
16
12
|
* @example
|
|
17
13
|
* // ◀️ before
|
|
@@ -7,16 +7,8 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
7
7
|
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Rewrites
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Plain methods stay concise because a function property would gain construction
|
|
14
|
-
* and `prototype`. Generator and async functions remain non-constructors. Any
|
|
15
|
-
* method using `super` also stays intact because a function has no HomeObject.
|
|
16
|
-
*
|
|
17
|
-
* Non-computed `__proto__` methods stay intact because the property form invokes
|
|
18
|
-
* ECMA-262 B.3.1 prototype-setting behavior. Computed keys create own properties
|
|
19
|
-
* and can be rewritten.
|
|
10
|
+
* Rewrites eligible async and generator object methods as function-valued
|
|
11
|
+
* properties.
|
|
20
12
|
*
|
|
21
13
|
* @example
|
|
22
14
|
* // ◀️ before
|
|
@@ -7,9 +7,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
7
7
|
import { buildNullishCheck } from '../utils/nullish'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Rewrites optional chains as
|
|
11
|
-
*
|
|
12
|
-
* to `true` as required by ECMA-262 13.5.1.
|
|
10
|
+
* Rewrites optional chains as equivalent conditional expressions while
|
|
11
|
+
* preserving short-circuiting and method receivers.
|
|
13
12
|
*
|
|
14
13
|
* @example
|
|
15
14
|
* // ◀️ before
|
|
@@ -8,11 +8,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
8
8
|
import { isLiteralShaped } from '../utils/literal'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Moves leading
|
|
12
|
-
*
|
|
13
|
-
* callers that could fill a new slot stay unchanged.
|
|
14
|
-
*
|
|
15
|
-
* Packing also requires unchanged `arguments`, directive, and hoisting behavior.
|
|
11
|
+
* Moves eligible leading `var` declarations with literal initializers into
|
|
12
|
+
* trailing default parameters.
|
|
16
13
|
*
|
|
17
14
|
* @example
|
|
18
15
|
* // ◀️ before
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
import type { File } from '@babel/types'
|
|
3
|
+
|
|
4
|
+
import { rewriteStatementLists } from '../utils/statement-lists'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Combines adjacent expression statements with the comma operator and moves
|
|
8
|
+
* them into a following compatible statement when execution order is preserved.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // ◀️ before
|
|
12
|
+
* function run() {
|
|
13
|
+
* prepare();
|
|
14
|
+
* update();
|
|
15
|
+
* return finish();
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* // ▶️ after
|
|
19
|
+
* function run() {
|
|
20
|
+
* return prepare(), update(), finish();
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
export function packExpressions(ast: File): boolean {
|
|
24
|
+
return rewriteStatementLists(ast, (statements) =>
|
|
25
|
+
packStatementList(statements.map((path) => path.node)),
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type StatementLike = t.Program['body'][number]
|
|
30
|
+
|
|
31
|
+
function packStatementList(list: readonly StatementLike[]): StatementLike[] | null {
|
|
32
|
+
const out: StatementLike[] = []
|
|
33
|
+
let pending: t.ExpressionStatement[] = []
|
|
34
|
+
let changed = false
|
|
35
|
+
|
|
36
|
+
const flush = (): void => {
|
|
37
|
+
if (pending.length === 1) {
|
|
38
|
+
out.push(pending[0]!)
|
|
39
|
+
} else if (pending.length > 1) {
|
|
40
|
+
out.push(
|
|
41
|
+
t.expressionStatement(
|
|
42
|
+
expressionFrom(
|
|
43
|
+
flattenExpressions(pending.map((pendingStatement) => pendingStatement.expression)),
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
changed = true
|
|
48
|
+
}
|
|
49
|
+
pending = []
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const statement of list) {
|
|
53
|
+
if (t.isExpressionStatement(statement)) {
|
|
54
|
+
pending.push(statement)
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (pending.length > 0) {
|
|
59
|
+
const expressions = flattenExpressions(
|
|
60
|
+
pending.map((pendingStatement) => pendingStatement.expression),
|
|
61
|
+
)
|
|
62
|
+
if (prependToConsumer(statement, expressions)) {
|
|
63
|
+
out.push(statement)
|
|
64
|
+
pending = []
|
|
65
|
+
changed = true
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
flush()
|
|
71
|
+
out.push(statement)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
flush()
|
|
75
|
+
return changed ? out : null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function prependToConsumer(statement: StatementLike, expressions: t.Expression[]): boolean {
|
|
79
|
+
if (t.isReturnStatement(statement)) {
|
|
80
|
+
const argument = statement.argument ?? t.unaryExpression('void', t.numericLiteral(0))
|
|
81
|
+
statement.argument = prependExpressions(expressions, argument)
|
|
82
|
+
return true
|
|
83
|
+
}
|
|
84
|
+
if (t.isThrowStatement(statement)) {
|
|
85
|
+
statement.argument = prependExpressions(expressions, statement.argument)
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
if (t.isIfStatement(statement)) {
|
|
89
|
+
statement.test = prependExpressions(expressions, statement.test)
|
|
90
|
+
return true
|
|
91
|
+
}
|
|
92
|
+
if (t.isSwitchStatement(statement)) {
|
|
93
|
+
statement.discriminant = prependExpressions(expressions, statement.discriminant)
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
96
|
+
if (t.isWithStatement(statement)) {
|
|
97
|
+
statement.object = prependExpressions(expressions, statement.object)
|
|
98
|
+
return true
|
|
99
|
+
}
|
|
100
|
+
if (t.isForStatement(statement)) {
|
|
101
|
+
if (t.isVariableDeclaration(statement.init)) {
|
|
102
|
+
return false
|
|
103
|
+
}
|
|
104
|
+
statement.init = statement.init
|
|
105
|
+
? prependExpressions(expressions, statement.init)
|
|
106
|
+
: expressionFrom(expressions)
|
|
107
|
+
return true
|
|
108
|
+
}
|
|
109
|
+
if (t.isForInStatement(statement) || t.isForOfStatement(statement)) {
|
|
110
|
+
if (!canPrependToForXRight(statement.left)) {
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
statement.right = prependExpressions(expressions, statement.right)
|
|
114
|
+
return true
|
|
115
|
+
}
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function canPrependToForXRight(left: t.ForInStatement['left']): boolean {
|
|
120
|
+
if (!t.isVariableDeclaration(left)) {
|
|
121
|
+
return true
|
|
122
|
+
}
|
|
123
|
+
// A lexical loop head is active while the right side runs; a preceding
|
|
124
|
+
// statement is outside it. A legacy var initializer also runs before the
|
|
125
|
+
// right side.
|
|
126
|
+
return left.kind === 'var' && left.declarations.every((declaration) => !declaration.init)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function flattenExpressions(input: readonly t.Expression[]): t.Expression[] {
|
|
130
|
+
const remaining: t.Expression[] = []
|
|
131
|
+
for (let index = input.length - 1; index >= 0; index--) {
|
|
132
|
+
remaining.push(input[index]!)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const expressions: t.Expression[] = []
|
|
136
|
+
while (remaining.length > 0) {
|
|
137
|
+
const expression = remaining.pop()!
|
|
138
|
+
if (t.isSequenceExpression(expression)) {
|
|
139
|
+
for (let index = expression.expressions.length - 1; index >= 0; index--) {
|
|
140
|
+
remaining.push(expression.expressions[index]!)
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
expressions.push(expression)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return expressions
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function prependExpressions(
|
|
150
|
+
expressions: readonly t.Expression[],
|
|
151
|
+
consumer: t.Expression,
|
|
152
|
+
): t.Expression {
|
|
153
|
+
const flattenedConsumer = flattenExpressions([consumer])
|
|
154
|
+
return expressionFrom([...expressions, ...flattenedConsumer])
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function expressionFrom(expressions: t.Expression[]): t.Expression {
|
|
158
|
+
return expressions.length === 1 ? expressions[0]! : t.sequenceExpression(expressions)
|
|
159
|
+
}
|
package/src/transforms/pack.ts
CHANGED
|
@@ -107,10 +107,8 @@ const STANDARD_GLOBALS: readonly string[] = [
|
|
|
107
107
|
]
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* Serializes the
|
|
111
|
-
*
|
|
112
|
-
* names go through accessors created in the original top-level scope. Export
|
|
113
|
-
* statements are rejected because they cannot appear in a `Function` body.
|
|
110
|
+
* Serializes the program and executes it through a generated `Function`
|
|
111
|
+
* constructor.
|
|
114
112
|
*
|
|
115
113
|
* @example
|
|
116
114
|
* // ◀️ before
|
|
@@ -6,10 +6,8 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Removes statements
|
|
10
|
-
*
|
|
11
|
-
* Hoisted function and `var` declarations stay because reachable code may still
|
|
12
|
-
* observe their bindings.
|
|
9
|
+
* Removes unreachable statements that follow unconditional control flow while
|
|
10
|
+
* retaining declarations whose hoisting can still be observed.
|
|
13
11
|
*
|
|
14
12
|
* @example
|
|
15
13
|
* // ◀️ before
|
|
@@ -7,8 +7,8 @@ import { isSideEffectFree } from '../analysis/purity'
|
|
|
7
7
|
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Removes unused declarations and expression statements
|
|
11
|
-
*
|
|
10
|
+
* Removes unused declarations and side-effect-free expression statements until
|
|
11
|
+
* no further code becomes unused.
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* // ◀️ before
|
|
@@ -9,9 +9,8 @@ import { mulberry32 } from '../utils/random'
|
|
|
9
9
|
import { StringGenerator } from '../utils/string-generator'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Renames bindings and labels with the configured string generator
|
|
13
|
-
*
|
|
14
|
-
* scope. Separate sibling scopes may reuse the same names.
|
|
12
|
+
* Renames bindings and labels with the configured string generator while
|
|
13
|
+
* avoiding name capture.
|
|
15
14
|
*
|
|
16
15
|
* @example
|
|
17
16
|
* // ◀️ before
|
|
@@ -6,12 +6,8 @@ import { rewriteStatementLists } from '../utils/statement-lists'
|
|
|
6
6
|
import type { StatementListContainer } from '../utils/statement-lists'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Moves hoisted function declarations to the end of
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* If moving every declaration would turn a string expression into a directive,
|
|
13
|
-
* one declaration stays before the string. Direct exports stay in place.
|
|
14
|
-
* Indirect exports move with their local declaration.
|
|
9
|
+
* Moves hoisted function declarations to the end of their statement lists
|
|
10
|
+
* without changing their relative order.
|
|
15
11
|
*
|
|
16
12
|
* @example
|
|
17
13
|
* // ◀️ before
|
|
@@ -9,19 +9,8 @@ import { mulberry32 } from '../utils/random'
|
|
|
9
9
|
import { StringGenerator } from '../utils/string-generator'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Rewrites
|
|
13
|
-
*
|
|
14
|
-
* - `true` -> `!!"<random>"`
|
|
15
|
-
* - `false` -> `!"<random>"`
|
|
16
|
-
* - `NaN` -> `+"<random>"`
|
|
17
|
-
* - `undefined`-> `void "<random>"`
|
|
18
|
-
* - `Infinity` -> `1/!"<random>"`
|
|
19
|
-
*
|
|
20
|
-
* Generated strings are nonempty and nonnumeric, fixing their truthiness and
|
|
21
|
-
* numeric coercion.
|
|
22
|
-
*
|
|
23
|
-
* `NaN`, `Infinity`, and `undefined` require genuine global reads. Delete and
|
|
24
|
-
* write positions stay unchanged because the replacement is not a reference.
|
|
12
|
+
* Rewrites `true`, `false`, `NaN`, `undefined`, and `Infinity` as equivalent
|
|
13
|
+
* expressions built from strings.
|
|
25
14
|
*
|
|
26
15
|
* @example
|
|
27
16
|
* // ◀️ before
|
|
@@ -9,10 +9,9 @@ import { isPrimitiveLiteral } from '../utils/literal'
|
|
|
9
9
|
import { generateLoopLabel } from '../utils/loop-lowering'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `if` blocks cannot preserve the shared switch scope.
|
|
12
|
+
* Rewrites eligible `switch` statements as equivalent `if` statements, using a
|
|
13
|
+
* labeled block when fallthrough must be preserved. Switches whose shared case
|
|
14
|
+
* scope cannot be preserved stay unchanged.
|
|
16
15
|
*
|
|
17
16
|
* @example
|
|
18
17
|
* // ◀️ before
|
|
@@ -8,9 +8,8 @@ import { isConditionalGate, reorderableToStatement } from '../utils/evaluation-o
|
|
|
8
8
|
import { isStandaloneDeclaration } from '../utils/paths'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* temporary
|
|
13
|
-
* hoisting would change when they run.
|
|
11
|
+
* Rewrites eligible conditional expressions as `if` statements, using a
|
|
12
|
+
* temporary when their value is needed.
|
|
14
13
|
*
|
|
15
14
|
* @example
|
|
16
15
|
* // ◀️ before
|
|
@@ -6,12 +6,8 @@ import { traverseForChanges } from '../utils/change-tracking'
|
|
|
6
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Rewrites numeric
|
|
10
|
-
*
|
|
11
|
-
* value.
|
|
12
|
-
*
|
|
13
|
-
* BigInt differs because adding the number `1` throws. Only bindings proven to
|
|
14
|
-
* stay numeric are rewritten. Members and parameters stay unchanged.
|
|
9
|
+
* Rewrites eligible numeric update expressions as compound assignments. Postfix
|
|
10
|
+
* updates stay unchanged when their original value is used.
|
|
15
11
|
*
|
|
16
12
|
* @example
|
|
17
13
|
* // ◀️ before
|
|
@@ -7,9 +7,8 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
7
7
|
import { isLiteralShaped } from '../utils/literal'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Moves
|
|
11
|
-
*
|
|
12
|
-
* are flipped after swapping.
|
|
10
|
+
* Moves eligible literal-like right operands to the left side of comparisons,
|
|
11
|
+
* reversing relational operators as needed.
|
|
13
12
|
*
|
|
14
13
|
* @example
|
|
15
14
|
* // ◀️ before
|