webfuscator 1.0.1 → 1.2.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/README.md +0 -2
- package/dist/analysis/constant.js +3 -3
- package/dist/analysis/constant.js.map +1 -1
- package/dist/analysis/inlineability.js +2 -2
- package/dist/analysis/inlineability.js.map +1 -1
- package/dist/analysis/purity.js +1 -1
- package/dist/analysis/purity.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/obfuscator.d.ts.map +1 -1
- package/dist/obfuscator.js +14 -0
- package/dist/obfuscator.js.map +1 -1
- package/dist/options.d.ts +14 -2
- package/dist/options.d.ts.map +1 -1
- package/dist/preparation/expand-destructuring.js +4 -3
- package/dist/preparation/expand-destructuring.js.map +1 -1
- package/dist/preparation/expand-template-literals.js +3 -2
- package/dist/preparation/expand-template-literals.js.map +1 -1
- package/dist/preparation/split-sequence-expressions.js +1 -1
- package/dist/preparation/split-sequence-expressions.js.map +1 -1
- package/dist/preparation/split-variable-declarations.js +1 -1
- package/dist/preparation/split-variable-declarations.js.map +1 -1
- package/dist/preparation/stringify-object-keys.js +1 -1
- package/dist/preparation/stringify-object-keys.js.map +1 -1
- package/dist/preparation/wrap-single-statements.js +2 -2
- package/dist/preparation/wrap-single-statements.js.map +1 -1
- package/dist/transforms/arguments-to-parameters.js +1 -1
- package/dist/transforms/arguments-to-parameters.js.map +1 -1
- package/dist/transforms/arrow-to-function.js.map +1 -1
- package/dist/transforms/collapse-single-use-temps.js +7 -7
- package/dist/transforms/collapse-single-use-temps.js.map +1 -1
- package/dist/transforms/const-let-to-var.js +3 -3
- package/dist/transforms/const-let-to-var.js.map +1 -1
- package/dist/transforms/const-to-let.js.map +1 -1
- package/dist/transforms/do-while-to-while.js +3 -3
- package/dist/transforms/do-while-to-while.js.map +1 -1
- package/dist/transforms/drop-console.js +4 -3
- package/dist/transforms/drop-console.js.map +1 -1
- package/dist/transforms/drop-debugger.js.map +1 -1
- package/dist/transforms/expand-binary-assignment.js +5 -3
- package/dist/transforms/expand-binary-assignment.js.map +1 -1
- package/dist/transforms/expand-logical-assignment.js +5 -3
- package/dist/transforms/expand-logical-assignment.js.map +1 -1
- package/dist/transforms/extract-object-properties.js +7 -7
- package/dist/transforms/extract-object-properties.js.map +1 -1
- package/dist/transforms/fold-builtin-methods.js +16 -15
- package/dist/transforms/fold-builtin-methods.js.map +1 -1
- package/dist/transforms/fold-constants.js +2 -2
- package/dist/transforms/fold-constants.js.map +1 -1
- package/dist/transforms/for-to-while.js +5 -5
- package/dist/transforms/for-to-while.js.map +1 -1
- package/dist/transforms/function-declaration-to-expression.js +3 -3
- package/dist/transforms/function-declaration-to-expression.js.map +1 -1
- package/dist/transforms/inline-functions.js +7 -7
- package/dist/transforms/inline-functions.js.map +1 -1
- package/dist/transforms/logical-to-ternary.js +2 -2
- package/dist/transforms/logical-to-ternary.js.map +1 -1
- package/dist/transforms/mangle-properties.d.ts.map +1 -1
- package/dist/transforms/mangle-properties.js +35 -86
- package/dist/transforms/mangle-properties.js.map +1 -1
- package/dist/transforms/nullish-coalescing-to-ternary.js +2 -2
- package/dist/transforms/nullish-coalescing-to-ternary.js.map +1 -1
- package/dist/transforms/numbers-to-strings.js +2 -2
- package/dist/transforms/numbers-to-strings.js.map +1 -1
- package/dist/transforms/object-method-to-property.js +1 -1
- package/dist/transforms/object-method-to-property.js.map +1 -1
- package/dist/transforms/optional-chaining-to-ternary.js +7 -4
- package/dist/transforms/optional-chaining-to-ternary.js.map +1 -1
- package/dist/transforms/pack-declarations-into-parameters.js +2 -2
- package/dist/transforms/pack-declarations-into-parameters.js.map +1 -1
- package/dist/transforms/pack.d.ts +33 -0
- package/dist/transforms/pack.d.ts.map +1 -0
- package/dist/transforms/pack.js +265 -0
- package/dist/transforms/pack.js.map +1 -0
- package/dist/transforms/remove-anonymous-function-names.js +3 -3
- package/dist/transforms/remove-anonymous-function-names.js.map +1 -1
- package/dist/transforms/remove-unreachable-code.js +1 -1
- package/dist/transforms/remove-unreachable-code.js.map +1 -1
- package/dist/transforms/remove-unused-code.js +4 -4
- package/dist/transforms/remove-unused-code.js.map +1 -1
- package/dist/transforms/rename-identifiers.d.ts.map +1 -1
- package/dist/transforms/rename-identifiers.js +4 -3
- package/dist/transforms/rename-identifiers.js.map +1 -1
- package/dist/transforms/specials-to-strings.d.ts.map +1 -1
- package/dist/transforms/specials-to-strings.js +2 -2
- package/dist/transforms/specials-to-strings.js.map +1 -1
- package/dist/transforms/switch-to-if.js +7 -7
- package/dist/transforms/switch-to-if.js.map +1 -1
- package/dist/transforms/ternary-to-if.js +7 -4
- package/dist/transforms/ternary-to-if.js.map +1 -1
- package/dist/transforms/update-to-assignment.js +4 -2
- package/dist/transforms/update-to-assignment.js.map +1 -1
- package/dist/transforms/yodify-conditions.js +3 -3
- package/dist/transforms/yodify-conditions.js.map +1 -1
- package/dist/utils/ast.d.ts.map +1 -1
- package/dist/utils/ast.js +7 -2
- package/dist/utils/ast.js.map +1 -1
- package/dist/utils/evaluation-order.js.map +1 -1
- package/dist/utils/logical-lowering.js +2 -2
- package/dist/utils/logical-lowering.js.map +1 -1
- package/dist/utils/loop-lowering.js +1 -1
- package/dist/utils/loop-lowering.js.map +1 -1
- package/dist/utils/string-generator.js +1 -1
- package/dist/utils/string-generator.js.map +1 -1
- package/package.json +11 -10
- package/src/analysis/constant.ts +4 -4
- package/src/analysis/inlineability.ts +4 -4
- package/src/analysis/purity.ts +3 -3
- package/src/index.ts +9 -2
- package/src/obfuscator.ts +57 -41
- package/src/options.ts +16 -2
- package/src/preparation/expand-destructuring.ts +5 -4
- package/src/preparation/expand-template-literals.ts +4 -3
- package/src/preparation/split-sequence-expressions.ts +2 -2
- package/src/preparation/split-variable-declarations.ts +1 -1
- package/src/preparation/stringify-object-keys.ts +2 -2
- package/src/preparation/wrap-single-statements.ts +2 -2
- package/src/transforms/arguments-to-parameters.ts +5 -5
- package/src/transforms/arrow-to-function.ts +3 -3
- package/src/transforms/collapse-single-use-temps.ts +14 -14
- package/src/transforms/const-let-to-var.ts +6 -6
- package/src/transforms/const-to-let.ts +4 -4
- package/src/transforms/do-while-to-while.ts +6 -6
- package/src/transforms/drop-console.ts +8 -7
- package/src/transforms/drop-debugger.ts +2 -2
- package/src/transforms/expand-binary-assignment.ts +8 -6
- package/src/transforms/expand-logical-assignment.ts +8 -6
- package/src/transforms/extract-object-properties.ts +12 -12
- package/src/transforms/fold-builtin-methods.ts +20 -19
- package/src/transforms/fold-constants.ts +8 -8
- package/src/transforms/for-to-while.ts +8 -8
- package/src/transforms/function-declaration-to-expression.ts +5 -5
- package/src/transforms/inline-functions.ts +14 -14
- package/src/transforms/logical-to-ternary.ts +7 -7
- package/src/transforms/mangle-properties.ts +43 -97
- package/src/transforms/nullish-coalescing-to-ternary.ts +6 -6
- package/src/transforms/numbers-to-strings.ts +4 -4
- package/src/transforms/object-method-to-property.ts +4 -4
- package/src/transforms/optional-chaining-to-ternary.ts +10 -7
- package/src/transforms/pack-declarations-into-parameters.ts +7 -7
- package/src/transforms/pack.ts +340 -0
- package/src/transforms/remove-anonymous-function-names.ts +5 -5
- package/src/transforms/remove-unreachable-code.ts +3 -3
- package/src/transforms/remove-unused-code.ts +8 -8
- package/src/transforms/rename-identifiers.ts +9 -8
- package/src/transforms/specials-to-strings.ts +7 -7
- package/src/transforms/switch-to-if.ts +12 -12
- package/src/transforms/ternary-to-if.ts +12 -9
- package/src/transforms/update-to-assignment.ts +7 -5
- package/src/transforms/yodify-conditions.ts +6 -6
- package/src/utils/ast.ts +9 -2
- package/src/utils/evaluation-order.ts +1 -1
- package/src/utils/logical-lowering.ts +3 -3
- package/src/utils/loop-lowering.ts +1 -1
- package/src/utils/string-generator.ts +1 -1
|
@@ -2,8 +2,8 @@ import type { Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { traverseForChanges } from '
|
|
6
|
-
import type { ChangeState } from '
|
|
5
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Removes every `debugger` statement.
|
|
@@ -2,9 +2,9 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { isInsideWith } from '
|
|
6
|
-
import { traverseForChanges } from '
|
|
7
|
-
import type { ChangeState } from '
|
|
5
|
+
import { isInsideWith } from '../utils/ast'
|
|
6
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Rewrites arithmetic and bitwise compound assignments as `LHS = LHS op RHS`.
|
|
@@ -44,7 +44,9 @@ const visitor: Visitor<ChangeState> = {
|
|
|
44
44
|
const LOGICAL_COMPOUND = new Set(['||', '&&', '??'])
|
|
45
45
|
|
|
46
46
|
function lowerBinaryAssignment(path: NodePath<t.AssignmentExpression>): boolean {
|
|
47
|
-
const
|
|
47
|
+
const operator = path.node.operator
|
|
48
|
+
const left = path.node.left
|
|
49
|
+
const right = path.node.right
|
|
48
50
|
if (operator === '=' || operator.length < 2) {
|
|
49
51
|
return false
|
|
50
52
|
}
|
|
@@ -60,7 +62,7 @@ function lowerBinaryAssignment(path: NodePath<t.AssignmentExpression>): boolean
|
|
|
60
62
|
if (isInsideWith(path)) {
|
|
61
63
|
return false
|
|
62
64
|
}
|
|
63
|
-
const
|
|
65
|
+
const object = left.object
|
|
64
66
|
if (t.isExpression(object)) {
|
|
65
67
|
const memo = path.scope.maybeGenerateMemoised(object)
|
|
66
68
|
if (memo) {
|
|
@@ -70,7 +72,7 @@ function lowerBinaryAssignment(path: NodePath<t.AssignmentExpression>): boolean
|
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
if (left.computed) {
|
|
73
|
-
const
|
|
75
|
+
const property = left.property
|
|
74
76
|
if (t.isExpression(property)) {
|
|
75
77
|
const memoProp = path.scope.maybeGenerateMemoised(property)
|
|
76
78
|
if (memoProp) {
|
|
@@ -2,9 +2,9 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { isInsideWith } from '
|
|
6
|
-
import { traverseForChanges } from '
|
|
7
|
-
import type { ChangeState } from '
|
|
5
|
+
import { isInsideWith } from '../utils/ast'
|
|
6
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Rewrites `||=`/`&&=`/`??=` as `LHS op (LHS = RHS)`. Member objects and
|
|
@@ -38,7 +38,9 @@ const visitor: Visitor<ChangeState> = {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function lowerLogicalAssignment(path: NodePath<t.AssignmentExpression>): boolean {
|
|
41
|
-
const
|
|
41
|
+
const operator = path.node.operator
|
|
42
|
+
const left = path.node.left
|
|
43
|
+
const right = path.node.right
|
|
42
44
|
if (operator.length < 2) {
|
|
43
45
|
return false
|
|
44
46
|
}
|
|
@@ -54,7 +56,7 @@ function lowerLogicalAssignment(path: NodePath<t.AssignmentExpression>): boolean
|
|
|
54
56
|
if (isInsideWith(path)) {
|
|
55
57
|
return false
|
|
56
58
|
}
|
|
57
|
-
const
|
|
59
|
+
const object = left.object
|
|
58
60
|
if (t.isExpression(object)) {
|
|
59
61
|
const memo = path.scope.maybeGenerateMemoised(object)
|
|
60
62
|
if (memo) {
|
|
@@ -64,7 +66,7 @@ function lowerLogicalAssignment(path: NodePath<t.AssignmentExpression>): boolean
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
if (left.computed) {
|
|
67
|
-
const
|
|
69
|
+
const property = left.property
|
|
68
70
|
if (t.isExpression(property)) {
|
|
69
71
|
const memoProp = path.scope.maybeGenerateMemoised(property)
|
|
70
72
|
if (memoProp) {
|
|
@@ -2,11 +2,11 @@ import type { Binding, NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { initializerReaches } from '
|
|
6
|
-
import { isInsideWith, isProtoKey } from '
|
|
7
|
-
import { traverseForChanges } from '
|
|
8
|
-
import type { ChangeState } from '
|
|
9
|
-
import { isCalleeOrTagOf } from '
|
|
5
|
+
import { initializerReaches } from '../analysis/document-order'
|
|
6
|
+
import { isInsideWith, isProtoKey } from '../utils/ast'
|
|
7
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
8
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
9
|
+
import { isCalleeOrTagOf } from '../utils/paths'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Replaces a constant object or array wrapper with one binding per entry when
|
|
@@ -48,7 +48,7 @@ function tryExtractDeclaration(path: NodePath<t.VariableDeclaration>): boolean {
|
|
|
48
48
|
if (path.key === 'init' && path.parentPath?.isForStatement() && path.node.kind !== 'var') {
|
|
49
49
|
return false
|
|
50
50
|
}
|
|
51
|
-
const
|
|
51
|
+
const declaratorPath = path.get('declarations')[0]
|
|
52
52
|
if (!declaratorPath) {
|
|
53
53
|
return false
|
|
54
54
|
}
|
|
@@ -239,7 +239,7 @@ function performExtraction(
|
|
|
239
239
|
replacements.push({ memberPath: parent, key })
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
const
|
|
242
|
+
const scope = path.scope
|
|
243
243
|
const usedNames = new Set<string>()
|
|
244
244
|
const keyToName = new Map<string, string>()
|
|
245
245
|
for (const { key } of entries) {
|
|
@@ -257,9 +257,9 @@ function performExtraction(
|
|
|
257
257
|
keyToName.set(key, chosen)
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
const newDecls = entries.map((
|
|
260
|
+
const newDecls = entries.map((entry) =>
|
|
261
261
|
t.variableDeclaration(path.node.kind, [
|
|
262
|
-
t.variableDeclarator(t.identifier(keyToName.get(key)!), value),
|
|
262
|
+
t.variableDeclarator(t.identifier(keyToName.get(entry.key)!), entry.value),
|
|
263
263
|
]),
|
|
264
264
|
)
|
|
265
265
|
|
|
@@ -271,7 +271,7 @@ function performExtraction(
|
|
|
271
271
|
// Publish rewritten references for the next fixed-point iteration.
|
|
272
272
|
for (const { memberPath, key } of replacements) {
|
|
273
273
|
const name = keyToName.get(key)!
|
|
274
|
-
const
|
|
274
|
+
const newRefPath = memberPath.replaceWith(t.identifier(name))[0]
|
|
275
275
|
if (newRefPath) {
|
|
276
276
|
const refBinding = newRefPath.scope.getBinding(name)
|
|
277
277
|
if (refBinding) {
|
|
@@ -288,7 +288,7 @@ function performExtraction(
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
function staticPropertyKey(prop: t.ObjectProperty): string | null {
|
|
291
|
-
const
|
|
291
|
+
const key = prop.key
|
|
292
292
|
if (!prop.computed && t.isIdentifier(key)) {
|
|
293
293
|
return key.name
|
|
294
294
|
}
|
|
@@ -359,7 +359,7 @@ function isWriteTargetMember(memberPath: NodePath<t.MemberExpression>): boolean
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
function functionRefsThis(path: NodePath): boolean {
|
|
362
|
-
const
|
|
362
|
+
const node = path.node
|
|
363
363
|
if (!t.isFunctionExpression(node) && !t.isFunctionDeclaration(node)) {
|
|
364
364
|
return false
|
|
365
365
|
}
|
|
@@ -3,10 +3,10 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
3
3
|
import * as t from '@babel/types'
|
|
4
4
|
import type { File } from '@babel/types'
|
|
5
5
|
|
|
6
|
-
import { evaluateConstant, isOpaque } from '
|
|
7
|
-
import { enclosingScopeHasDirectEval, isInDirectivePrologue, isInsideWith } from '
|
|
8
|
-
import type { ChangeState } from '
|
|
9
|
-
import { valueToLiteral } from '
|
|
6
|
+
import { evaluateConstant, isOpaque } from '../analysis/constant'
|
|
7
|
+
import { enclosingScopeHasDirectEval, isInDirectivePrologue, isInsideWith } from '../utils/ast'
|
|
8
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
9
|
+
import { valueToLiteral } from '../utils/literal'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Replaces built-in calls and reads with smaller syntax or host-computed
|
|
@@ -105,7 +105,7 @@ function collectPatchedIntrinsics(ast: File): Set<string> {
|
|
|
105
105
|
},
|
|
106
106
|
Identifier(path) {
|
|
107
107
|
// Global eval and Function can patch any intrinsic outside this scan.
|
|
108
|
-
const
|
|
108
|
+
const name = path.node.name
|
|
109
109
|
if (name !== 'eval' && name !== 'Function') {
|
|
110
110
|
return
|
|
111
111
|
}
|
|
@@ -163,7 +163,7 @@ function markWriteTarget(target: t.Node, scope: NodePath['scope'], poison: Poiso
|
|
|
163
163
|
|
|
164
164
|
// Only genuine Object and Reflect bulk mutation methods count as patches.
|
|
165
165
|
function markMutationCall(path: NodePath<t.CallExpression>, poison: PoisonSink): void {
|
|
166
|
-
const
|
|
166
|
+
const callee = path.node.callee
|
|
167
167
|
// Preparation may already have changed the method to bracket syntax.
|
|
168
168
|
if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.object)) {
|
|
169
169
|
return
|
|
@@ -175,7 +175,7 @@ function markMutationCall(path: NodePath<t.CallExpression>, poison: PoisonSink):
|
|
|
175
175
|
if (!isMutatingIntrinsicMethod(callee.object.name, method)) {
|
|
176
176
|
return
|
|
177
177
|
}
|
|
178
|
-
const
|
|
178
|
+
const firstArg = path.node.arguments[0]
|
|
179
179
|
if (!firstArg || !t.isExpression(firstArg)) {
|
|
180
180
|
return
|
|
181
181
|
}
|
|
@@ -461,12 +461,12 @@ function staticPropertyName(node: t.MemberExpression): string | null {
|
|
|
461
461
|
// Write targets require references. A folded literal would be invalid syntax,
|
|
462
462
|
// including when the member sits inside a destructuring target.
|
|
463
463
|
function isReferenceRequiredPosition(path: NodePath<t.MemberExpression>): boolean {
|
|
464
|
-
const
|
|
464
|
+
const parentPath = path.parentPath
|
|
465
465
|
if (!parentPath) {
|
|
466
466
|
return false
|
|
467
467
|
}
|
|
468
468
|
const parent = parentPath.node
|
|
469
|
-
const
|
|
469
|
+
const node = path.node
|
|
470
470
|
if (t.isAssignmentExpression(parent) && parent.left === node) {
|
|
471
471
|
return true
|
|
472
472
|
}
|
|
@@ -500,7 +500,7 @@ function foldsIntoDirective(path: NodePath<t.CallExpression>, replacement: t.Exp
|
|
|
500
500
|
if (!t.isStringLiteral(replacement)) {
|
|
501
501
|
return false
|
|
502
502
|
}
|
|
503
|
-
const
|
|
503
|
+
const parentPath = path.parentPath
|
|
504
504
|
return (
|
|
505
505
|
parentPath != null && parentPath.isExpressionStatement() && isInDirectivePrologue(parentPath)
|
|
506
506
|
)
|
|
@@ -511,7 +511,7 @@ function handleCall(path: NodePath<t.CallExpression>, patchedRoots: Set<string>)
|
|
|
511
511
|
if (isInsideWith(path) || enclosingScopeHasDirectEval(path)) {
|
|
512
512
|
return
|
|
513
513
|
}
|
|
514
|
-
const
|
|
514
|
+
const callee = path.node.callee
|
|
515
515
|
|
|
516
516
|
if (t.isIdentifier(callee)) {
|
|
517
517
|
foldGlobalCall(path, callee.name, patchedRoots)
|
|
@@ -545,7 +545,7 @@ function handleMember(path: NodePath<t.MemberExpression>, patchedRoots: Set<stri
|
|
|
545
545
|
return
|
|
546
546
|
}
|
|
547
547
|
|
|
548
|
-
const
|
|
548
|
+
const parent = path.parent
|
|
549
549
|
// Calls use their own folding path.
|
|
550
550
|
if (
|
|
551
551
|
(t.isCallExpression(parent) ||
|
|
@@ -700,7 +700,7 @@ function foldReceiverCall(
|
|
|
700
700
|
if (!recv.known) {
|
|
701
701
|
return
|
|
702
702
|
}
|
|
703
|
-
const
|
|
703
|
+
const value = recv.value
|
|
704
704
|
|
|
705
705
|
if (typeof value === 'string') {
|
|
706
706
|
if (!STRING_PROTOTYPE_METHODS.has(method) || patchedRoots.has('String')) {
|
|
@@ -736,7 +736,8 @@ function foldMathPow(path: NodePath<t.CallExpression>): void {
|
|
|
736
736
|
if (args.length !== 2) {
|
|
737
737
|
return
|
|
738
738
|
}
|
|
739
|
-
const
|
|
739
|
+
const left = args[0]
|
|
740
|
+
const right = args[1]
|
|
740
741
|
if (!t.isExpression(left) || !t.isExpression(right)) {
|
|
741
742
|
return
|
|
742
743
|
}
|
|
@@ -778,7 +779,7 @@ function foldArrayIsArray(path: NodePath<t.CallExpression>): void {
|
|
|
778
779
|
if (args.length !== 1) {
|
|
779
780
|
return
|
|
780
781
|
}
|
|
781
|
-
const
|
|
782
|
+
const arg = args[0]
|
|
782
783
|
if (!t.isExpression(arg)) {
|
|
783
784
|
return
|
|
784
785
|
}
|
|
@@ -787,7 +788,7 @@ function foldArrayIsArray(path: NodePath<t.CallExpression>): void {
|
|
|
787
788
|
if (!evaluated.known) {
|
|
788
789
|
return
|
|
789
790
|
}
|
|
790
|
-
const
|
|
791
|
+
const value = evaluated.value
|
|
791
792
|
if (
|
|
792
793
|
typeof value === 'string' ||
|
|
793
794
|
typeof value === 'number' ||
|
|
@@ -809,7 +810,7 @@ function foldBooleanCtor(path: NodePath<t.CallExpression>): void {
|
|
|
809
810
|
if (args.length !== 1) {
|
|
810
811
|
return
|
|
811
812
|
}
|
|
812
|
-
const
|
|
813
|
+
const arg = args[0]
|
|
813
814
|
if (!t.isExpression(arg)) {
|
|
814
815
|
return
|
|
815
816
|
}
|
|
@@ -828,7 +829,7 @@ function foldStringCtor(path: NodePath<t.CallExpression>): void {
|
|
|
828
829
|
if (args.length !== 1) {
|
|
829
830
|
return
|
|
830
831
|
}
|
|
831
|
-
const
|
|
832
|
+
const arg = args[0]
|
|
832
833
|
if (!t.isExpression(arg)) {
|
|
833
834
|
return
|
|
834
835
|
}
|
|
@@ -858,7 +859,7 @@ function foldNumberCtor(path: NodePath<t.CallExpression>): void {
|
|
|
858
859
|
if (args.length !== 1) {
|
|
859
860
|
return
|
|
860
861
|
}
|
|
861
|
-
const
|
|
862
|
+
const arg = args[0]
|
|
862
863
|
if (!t.isExpression(arg)) {
|
|
863
864
|
return
|
|
864
865
|
}
|
|
@@ -2,12 +2,12 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { evaluateConstant } from '
|
|
6
|
-
import { isPure } from '
|
|
7
|
-
import { traverseForChanges } from '
|
|
8
|
-
import type { ChangeState } from '
|
|
9
|
-
import { valueToLiteral } from '
|
|
10
|
-
import { isCalleeOrTagOf } from '
|
|
5
|
+
import { evaluateConstant } from '../analysis/constant'
|
|
6
|
+
import { isPure } from '../analysis/purity'
|
|
7
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
8
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
9
|
+
import { valueToLiteral } from '../utils/literal'
|
|
10
|
+
import { isCalleeOrTagOf } from '../utils/paths'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Folds pure constant expressions to literals via `evaluateConstant`.
|
|
@@ -243,7 +243,7 @@ function tryReassociateSubtract(path: NodePath<t.BinaryExpression>): boolean {
|
|
|
243
243
|
let node: t.BinaryExpression = path.node
|
|
244
244
|
while (true) {
|
|
245
245
|
subtractees.unshift(node.right)
|
|
246
|
-
const
|
|
246
|
+
const left = node.left
|
|
247
247
|
if (t.isBinaryExpression(left) && left.operator === '-') {
|
|
248
248
|
node = left
|
|
249
249
|
continue
|
|
@@ -359,7 +359,7 @@ function combineConstants(
|
|
|
359
359
|
if (consts.length === 0) {
|
|
360
360
|
return null
|
|
361
361
|
}
|
|
362
|
-
const
|
|
362
|
+
const kind = consts[0]!.kind
|
|
363
363
|
for (const c of consts) {
|
|
364
364
|
if (c.kind !== kind) {
|
|
365
365
|
return null
|
|
@@ -2,9 +2,9 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { traverseForChanges } from '
|
|
6
|
-
import type { ChangeState } from '
|
|
7
|
-
import { collectLoopLabels, generateLoopLabel, redirectContinues } from '
|
|
5
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
7
|
+
import { collectLoopLabels, generateLoopLabel, redirectContinues } from '../utils/loop-lowering'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Rewrites classic `for` loops as an initializer followed by `while`. Continues
|
|
@@ -45,14 +45,14 @@ const visitor: Visitor<ChangeState> = {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function transformFor(path: NodePath<t.ForStatement>): boolean {
|
|
48
|
-
const
|
|
48
|
+
const node = path.node
|
|
49
49
|
|
|
50
50
|
// One hoisted binding cannot preserve lexical per-iteration captures.
|
|
51
51
|
if (t.isVariableDeclaration(node.init) && node.init.kind !== 'var') {
|
|
52
52
|
return false
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const
|
|
55
|
+
const loopLabels = collectLoopLabels(path)
|
|
56
56
|
const innerLabel = generateLoopLabel(path, 'forIteration')
|
|
57
57
|
|
|
58
58
|
const initStmt = buildInitStatement(node.init)
|
|
@@ -71,8 +71,8 @@ function transformFor(path: NodePath<t.ForStatement>): boolean {
|
|
|
71
71
|
const test = node.test ?? t.booleanLiteral(true)
|
|
72
72
|
const whileStmt = t.whileStatement(test, t.blockStatement(whileBody))
|
|
73
73
|
|
|
74
|
-
const
|
|
75
|
-
const rewriteCount = redirectContinues(newPath, innerLabel, ourLabels)
|
|
74
|
+
const newPath = path.replaceWith(whileStmt)[0]
|
|
75
|
+
const rewriteCount = redirectContinues(newPath, innerLabel, loopLabels.ourLabels)
|
|
76
76
|
|
|
77
77
|
// Keep the block so body bindings cannot shadow names in the update.
|
|
78
78
|
if (rewriteCount === 0) {
|
|
@@ -80,7 +80,7 @@ function transformFor(path: NodePath<t.ForStatement>): boolean {
|
|
|
80
80
|
whileBlock.body[0] = blockBody
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
hoistInit(outermost, initStmt)
|
|
83
|
+
hoistInit(loopLabels.outermost, initStmt)
|
|
84
84
|
return true
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -2,8 +2,8 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { traverseForChanges } from '
|
|
6
|
-
import type { ChangeState } from '
|
|
5
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Rewrites safe function declarations as `var` initializers. The function value
|
|
@@ -36,11 +36,11 @@ export function functionDeclarationToExpression(ast: File): boolean {
|
|
|
36
36
|
|
|
37
37
|
const visitor: Visitor<ChangeState> = {
|
|
38
38
|
FunctionDeclaration(path, state) {
|
|
39
|
-
const
|
|
39
|
+
const id = path.node.id
|
|
40
40
|
if (!id || !isConvertible(path, id)) {
|
|
41
41
|
return
|
|
42
42
|
}
|
|
43
|
-
const
|
|
43
|
+
const node = path.node
|
|
44
44
|
const fn = t.functionExpression(null, node.params, node.body, node.generator, node.async)
|
|
45
45
|
path.replaceWith(t.variableDeclaration('var', [t.variableDeclarator(t.cloneNode(id), fn)]))
|
|
46
46
|
state.changed = true
|
|
@@ -66,7 +66,7 @@ function isConvertible(path: NodePath<t.FunctionDeclaration>, id: t.Identifier):
|
|
|
66
66
|
return false
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const
|
|
69
|
+
const body = (parent.node as t.Program | t.BlockStatement).body
|
|
70
70
|
const index = path.key as number
|
|
71
71
|
for (let i = 0; i < index; i++) {
|
|
72
72
|
if (!isInertStatement(body[i]!)) {
|
|
@@ -3,13 +3,13 @@ import type { NodePath, Scope } from '@babel/traverse'
|
|
|
3
3
|
import * as t from '@babel/types'
|
|
4
4
|
import type { File } from '@babel/types'
|
|
5
5
|
|
|
6
|
-
import { analyzeInlineability } from '
|
|
7
|
-
import type { InlineCandidate } from '
|
|
8
|
-
import { isPure } from '
|
|
9
|
-
import { enclosingScopeHasDirectEval, isInsideWith, walkOwnFunctionScope } from '
|
|
10
|
-
import { reorderableToStatement } from '
|
|
11
|
-
import { generateLoopLabel } from '
|
|
12
|
-
import { hasAnnexBFunctionAlias, isInStrictContext } from '
|
|
6
|
+
import { analyzeInlineability } from '../analysis/inlineability'
|
|
7
|
+
import type { InlineCandidate } from '../analysis/inlineability'
|
|
8
|
+
import { isPure } from '../analysis/purity'
|
|
9
|
+
import { enclosingScopeHasDirectEval, isInsideWith, walkOwnFunctionScope } from '../utils/ast'
|
|
10
|
+
import { reorderableToStatement } from '../utils/evaluation-order'
|
|
11
|
+
import { generateLoopLabel } from '../utils/loop-lowering'
|
|
12
|
+
import { hasAnnexBFunctionAlias, isInStrictContext } from '../utils/paths'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Replaces eligible calls with function bodies, working from inner calls out.
|
|
@@ -59,7 +59,7 @@ function tryInlineAtCallExpr(
|
|
|
59
59
|
path: NodePath<t.CallExpression>,
|
|
60
60
|
candidates: Map<string, InlineCandidate>,
|
|
61
61
|
): boolean {
|
|
62
|
-
const
|
|
62
|
+
const callee = path.node.callee
|
|
63
63
|
if (!t.isIdentifier(callee)) {
|
|
64
64
|
return false
|
|
65
65
|
}
|
|
@@ -123,7 +123,7 @@ function declarationIdentifier(declPath: NodePath): t.Identifier | null {
|
|
|
123
123
|
return declPath.node.id ?? null
|
|
124
124
|
}
|
|
125
125
|
if (declPath.isVariableDeclaration() && declPath.node.declarations.length === 1) {
|
|
126
|
-
const
|
|
126
|
+
const id = declPath.node.declarations[0]!.id
|
|
127
127
|
return t.isIdentifier(id) ? id : null
|
|
128
128
|
}
|
|
129
129
|
return null
|
|
@@ -209,7 +209,7 @@ function annexBHoistShadowsFreeVar(
|
|
|
209
209
|
path.skip()
|
|
210
210
|
},
|
|
211
211
|
FunctionDeclaration(path) {
|
|
212
|
-
const
|
|
212
|
+
const id = path.node.id
|
|
213
213
|
if (id && freeVars.has(id.name) && hasAnnexBFunctionAlias(path)) {
|
|
214
214
|
found = true
|
|
215
215
|
path.stop()
|
|
@@ -463,7 +463,7 @@ function inlineCallSite(
|
|
|
463
463
|
return false
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
const
|
|
466
|
+
const scope = stmtParent.scope
|
|
467
467
|
const labelName = generateLoopLabel(stmtParent, 'inlined')
|
|
468
468
|
|
|
469
469
|
// Returns can write directly into a bare assignment or `var` initializer.
|
|
@@ -660,7 +660,7 @@ function identifyDirectAssignmentTarget(
|
|
|
660
660
|
if (owner.isForOfStatement() && owner.node.left === declPath.node) {
|
|
661
661
|
return null
|
|
662
662
|
}
|
|
663
|
-
const
|
|
663
|
+
const name = parent.node.id.name
|
|
664
664
|
if (freeVars.has(name)) {
|
|
665
665
|
return null
|
|
666
666
|
}
|
|
@@ -680,7 +680,7 @@ function identifyDirectAssignmentTarget(
|
|
|
680
680
|
if (!stmt || !stmt.isExpressionStatement() || stmt.node.expression !== parent.node) {
|
|
681
681
|
return null
|
|
682
682
|
}
|
|
683
|
-
const
|
|
683
|
+
const name = parent.node.left.name
|
|
684
684
|
if (freeVars.has(name)) {
|
|
685
685
|
return null
|
|
686
686
|
}
|
|
@@ -782,7 +782,7 @@ function computeLiveFreeVars(candidate: InlineCandidate): Set<string> {
|
|
|
782
782
|
if (slot && isNonReferenceSlot(slot.node, slot.key)) {
|
|
783
783
|
return
|
|
784
784
|
}
|
|
785
|
-
const
|
|
785
|
+
const name = node.name
|
|
786
786
|
if (ownBound.has(name) || shadows.covers(name)) {
|
|
787
787
|
return
|
|
788
788
|
}
|
|
@@ -2,11 +2,11 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { isPure } from '
|
|
6
|
-
import { isInsideWith } from '
|
|
7
|
-
import { traverseForChanges } from '
|
|
8
|
-
import type { ChangeState } from '
|
|
9
|
-
import { lowerLogicalWriteStatement } from '
|
|
5
|
+
import { isPure } from '../analysis/purity'
|
|
6
|
+
import { isInsideWith } from '../utils/ast'
|
|
7
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
8
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
9
|
+
import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Rewrites logical expressions as guarded assignments or ternaries. A
|
|
@@ -40,7 +40,7 @@ const visitor: Visitor<ChangeState> = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
43
|
-
const
|
|
43
|
+
const node = path.node
|
|
44
44
|
const op = node.operator
|
|
45
45
|
if (op !== '&&' && op !== '||' && op !== '??') {
|
|
46
46
|
return false
|
|
@@ -54,7 +54,7 @@ function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
54
54
|
return true
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const
|
|
57
|
+
const scope = path.scope
|
|
58
58
|
const leftPath = path.get('left')
|
|
59
59
|
let testSrc: t.Expression
|
|
60
60
|
let valueSrc: t.Expression
|