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.
Files changed (156) hide show
  1. package/README.md +0 -2
  2. package/dist/analysis/constant.js +3 -3
  3. package/dist/analysis/constant.js.map +1 -1
  4. package/dist/analysis/inlineability.js +2 -2
  5. package/dist/analysis/inlineability.js.map +1 -1
  6. package/dist/analysis/purity.js +1 -1
  7. package/dist/analysis/purity.js.map +1 -1
  8. package/dist/index.d.ts +2 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/obfuscator.d.ts.map +1 -1
  12. package/dist/obfuscator.js +14 -0
  13. package/dist/obfuscator.js.map +1 -1
  14. package/dist/options.d.ts +14 -2
  15. package/dist/options.d.ts.map +1 -1
  16. package/dist/preparation/expand-destructuring.js +4 -3
  17. package/dist/preparation/expand-destructuring.js.map +1 -1
  18. package/dist/preparation/expand-template-literals.js +3 -2
  19. package/dist/preparation/expand-template-literals.js.map +1 -1
  20. package/dist/preparation/split-sequence-expressions.js +1 -1
  21. package/dist/preparation/split-sequence-expressions.js.map +1 -1
  22. package/dist/preparation/split-variable-declarations.js +1 -1
  23. package/dist/preparation/split-variable-declarations.js.map +1 -1
  24. package/dist/preparation/stringify-object-keys.js +1 -1
  25. package/dist/preparation/stringify-object-keys.js.map +1 -1
  26. package/dist/preparation/wrap-single-statements.js +2 -2
  27. package/dist/preparation/wrap-single-statements.js.map +1 -1
  28. package/dist/transforms/arguments-to-parameters.js +1 -1
  29. package/dist/transforms/arguments-to-parameters.js.map +1 -1
  30. package/dist/transforms/arrow-to-function.js.map +1 -1
  31. package/dist/transforms/collapse-single-use-temps.js +7 -7
  32. package/dist/transforms/collapse-single-use-temps.js.map +1 -1
  33. package/dist/transforms/const-let-to-var.js +3 -3
  34. package/dist/transforms/const-let-to-var.js.map +1 -1
  35. package/dist/transforms/const-to-let.js.map +1 -1
  36. package/dist/transforms/do-while-to-while.js +3 -3
  37. package/dist/transforms/do-while-to-while.js.map +1 -1
  38. package/dist/transforms/drop-console.js +4 -3
  39. package/dist/transforms/drop-console.js.map +1 -1
  40. package/dist/transforms/drop-debugger.js.map +1 -1
  41. package/dist/transforms/expand-binary-assignment.js +5 -3
  42. package/dist/transforms/expand-binary-assignment.js.map +1 -1
  43. package/dist/transforms/expand-logical-assignment.js +5 -3
  44. package/dist/transforms/expand-logical-assignment.js.map +1 -1
  45. package/dist/transforms/extract-object-properties.js +7 -7
  46. package/dist/transforms/extract-object-properties.js.map +1 -1
  47. package/dist/transforms/fold-builtin-methods.js +16 -15
  48. package/dist/transforms/fold-builtin-methods.js.map +1 -1
  49. package/dist/transforms/fold-constants.js +2 -2
  50. package/dist/transforms/fold-constants.js.map +1 -1
  51. package/dist/transforms/for-to-while.js +5 -5
  52. package/dist/transforms/for-to-while.js.map +1 -1
  53. package/dist/transforms/function-declaration-to-expression.js +3 -3
  54. package/dist/transforms/function-declaration-to-expression.js.map +1 -1
  55. package/dist/transforms/inline-functions.js +7 -7
  56. package/dist/transforms/inline-functions.js.map +1 -1
  57. package/dist/transforms/logical-to-ternary.js +2 -2
  58. package/dist/transforms/logical-to-ternary.js.map +1 -1
  59. package/dist/transforms/mangle-properties.d.ts.map +1 -1
  60. package/dist/transforms/mangle-properties.js +35 -86
  61. package/dist/transforms/mangle-properties.js.map +1 -1
  62. package/dist/transforms/nullish-coalescing-to-ternary.js +2 -2
  63. package/dist/transforms/nullish-coalescing-to-ternary.js.map +1 -1
  64. package/dist/transforms/numbers-to-strings.js +2 -2
  65. package/dist/transforms/numbers-to-strings.js.map +1 -1
  66. package/dist/transforms/object-method-to-property.js +1 -1
  67. package/dist/transforms/object-method-to-property.js.map +1 -1
  68. package/dist/transforms/optional-chaining-to-ternary.js +7 -4
  69. package/dist/transforms/optional-chaining-to-ternary.js.map +1 -1
  70. package/dist/transforms/pack-declarations-into-parameters.js +2 -2
  71. package/dist/transforms/pack-declarations-into-parameters.js.map +1 -1
  72. package/dist/transforms/pack.d.ts +33 -0
  73. package/dist/transforms/pack.d.ts.map +1 -0
  74. package/dist/transforms/pack.js +265 -0
  75. package/dist/transforms/pack.js.map +1 -0
  76. package/dist/transforms/remove-anonymous-function-names.js +3 -3
  77. package/dist/transforms/remove-anonymous-function-names.js.map +1 -1
  78. package/dist/transforms/remove-unreachable-code.js +1 -1
  79. package/dist/transforms/remove-unreachable-code.js.map +1 -1
  80. package/dist/transforms/remove-unused-code.js +4 -4
  81. package/dist/transforms/remove-unused-code.js.map +1 -1
  82. package/dist/transforms/rename-identifiers.d.ts.map +1 -1
  83. package/dist/transforms/rename-identifiers.js +4 -3
  84. package/dist/transforms/rename-identifiers.js.map +1 -1
  85. package/dist/transforms/specials-to-strings.d.ts.map +1 -1
  86. package/dist/transforms/specials-to-strings.js +2 -2
  87. package/dist/transforms/specials-to-strings.js.map +1 -1
  88. package/dist/transforms/switch-to-if.js +7 -7
  89. package/dist/transforms/switch-to-if.js.map +1 -1
  90. package/dist/transforms/ternary-to-if.js +7 -4
  91. package/dist/transforms/ternary-to-if.js.map +1 -1
  92. package/dist/transforms/update-to-assignment.js +4 -2
  93. package/dist/transforms/update-to-assignment.js.map +1 -1
  94. package/dist/transforms/yodify-conditions.js +3 -3
  95. package/dist/transforms/yodify-conditions.js.map +1 -1
  96. package/dist/utils/ast.d.ts.map +1 -1
  97. package/dist/utils/ast.js +7 -2
  98. package/dist/utils/ast.js.map +1 -1
  99. package/dist/utils/evaluation-order.js.map +1 -1
  100. package/dist/utils/logical-lowering.js +2 -2
  101. package/dist/utils/logical-lowering.js.map +1 -1
  102. package/dist/utils/loop-lowering.js +1 -1
  103. package/dist/utils/loop-lowering.js.map +1 -1
  104. package/dist/utils/string-generator.js +1 -1
  105. package/dist/utils/string-generator.js.map +1 -1
  106. package/package.json +11 -10
  107. package/src/analysis/constant.ts +4 -4
  108. package/src/analysis/inlineability.ts +4 -4
  109. package/src/analysis/purity.ts +3 -3
  110. package/src/index.ts +9 -2
  111. package/src/obfuscator.ts +57 -41
  112. package/src/options.ts +16 -2
  113. package/src/preparation/expand-destructuring.ts +5 -4
  114. package/src/preparation/expand-template-literals.ts +4 -3
  115. package/src/preparation/split-sequence-expressions.ts +2 -2
  116. package/src/preparation/split-variable-declarations.ts +1 -1
  117. package/src/preparation/stringify-object-keys.ts +2 -2
  118. package/src/preparation/wrap-single-statements.ts +2 -2
  119. package/src/transforms/arguments-to-parameters.ts +5 -5
  120. package/src/transforms/arrow-to-function.ts +3 -3
  121. package/src/transforms/collapse-single-use-temps.ts +14 -14
  122. package/src/transforms/const-let-to-var.ts +6 -6
  123. package/src/transforms/const-to-let.ts +4 -4
  124. package/src/transforms/do-while-to-while.ts +6 -6
  125. package/src/transforms/drop-console.ts +8 -7
  126. package/src/transforms/drop-debugger.ts +2 -2
  127. package/src/transforms/expand-binary-assignment.ts +8 -6
  128. package/src/transforms/expand-logical-assignment.ts +8 -6
  129. package/src/transforms/extract-object-properties.ts +12 -12
  130. package/src/transforms/fold-builtin-methods.ts +20 -19
  131. package/src/transforms/fold-constants.ts +8 -8
  132. package/src/transforms/for-to-while.ts +8 -8
  133. package/src/transforms/function-declaration-to-expression.ts +5 -5
  134. package/src/transforms/inline-functions.ts +14 -14
  135. package/src/transforms/logical-to-ternary.ts +7 -7
  136. package/src/transforms/mangle-properties.ts +43 -97
  137. package/src/transforms/nullish-coalescing-to-ternary.ts +6 -6
  138. package/src/transforms/numbers-to-strings.ts +4 -4
  139. package/src/transforms/object-method-to-property.ts +4 -4
  140. package/src/transforms/optional-chaining-to-ternary.ts +10 -7
  141. package/src/transforms/pack-declarations-into-parameters.ts +7 -7
  142. package/src/transforms/pack.ts +340 -0
  143. package/src/transforms/remove-anonymous-function-names.ts +5 -5
  144. package/src/transforms/remove-unreachable-code.ts +3 -3
  145. package/src/transforms/remove-unused-code.ts +8 -8
  146. package/src/transforms/rename-identifiers.ts +9 -8
  147. package/src/transforms/specials-to-strings.ts +7 -7
  148. package/src/transforms/switch-to-if.ts +12 -12
  149. package/src/transforms/ternary-to-if.ts +12 -9
  150. package/src/transforms/update-to-assignment.ts +7 -5
  151. package/src/transforms/yodify-conditions.ts +6 -6
  152. package/src/utils/ast.ts +9 -2
  153. package/src/utils/evaluation-order.ts +1 -1
  154. package/src/utils/logical-lowering.ts +3 -3
  155. package/src/utils/loop-lowering.ts +1 -1
  156. 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 'src/utils/change-tracking'
6
- import type { ChangeState } from 'src/utils/change-tracking'
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 'src/utils/ast'
6
- import { traverseForChanges } from 'src/utils/change-tracking'
7
- import type { ChangeState } from 'src/utils/change-tracking'
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 { operator, left, right } = path.node
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 { object } = left
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 { property } = left
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 'src/utils/ast'
6
- import { traverseForChanges } from 'src/utils/change-tracking'
7
- import type { ChangeState } from 'src/utils/change-tracking'
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 { operator, left, right } = path.node
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 { object } = left
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 { property } = left
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 'src/analysis/document-order'
6
- import { isInsideWith, isProtoKey } from 'src/utils/ast'
7
- import { traverseForChanges } from 'src/utils/change-tracking'
8
- import type { ChangeState } from 'src/utils/change-tracking'
9
- import { isCalleeOrTagOf } from 'src/utils/paths'
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 [declaratorPath] = path.get('declarations')
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 { scope } = path
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(({ key, value }) =>
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 [newRefPath] = memberPath.replaceWith(t.identifier(name))
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 { key } = prop
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 { node } = path
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 'src/analysis/constant'
7
- import { enclosingScopeHasDirectEval, isInDirectivePrologue, isInsideWith } from 'src/utils/ast'
8
- import type { ChangeState } from 'src/utils/change-tracking'
9
- import { valueToLiteral } from 'src/utils/literal'
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 { name } = path.node
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 { callee } = path.node
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 [firstArg] = path.node.arguments
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 { parentPath } = path
464
+ const parentPath = path.parentPath
465
465
  if (!parentPath) {
466
466
  return false
467
467
  }
468
468
  const parent = parentPath.node
469
- const { node } = path
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 { parentPath } = path
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 { callee } = path.node
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 { parent } = path
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 { value } = recv
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 [left, right] = args
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 [arg] = args
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 { value } = evaluated
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 [arg] = args
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 [arg] = args
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 [arg] = args
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 'src/analysis/constant'
6
- import { isPure } from 'src/analysis/purity'
7
- import { traverseForChanges } from 'src/utils/change-tracking'
8
- import type { ChangeState } from 'src/utils/change-tracking'
9
- import { valueToLiteral } from 'src/utils/literal'
10
- import { isCalleeOrTagOf } from 'src/utils/paths'
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 { left } = node
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 { kind } = consts[0]!
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 'src/utils/change-tracking'
6
- import type { ChangeState } from 'src/utils/change-tracking'
7
- import { collectLoopLabels, generateLoopLabel, redirectContinues } from 'src/utils/loop-lowering'
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 { node } = path
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 { outermost, ourLabels } = collectLoopLabels(path)
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 [newPath] = path.replaceWith(whileStmt)
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 'src/utils/change-tracking'
6
- import type { ChangeState } from 'src/utils/change-tracking'
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 { id } = path.node
39
+ const id = path.node.id
40
40
  if (!id || !isConvertible(path, id)) {
41
41
  return
42
42
  }
43
- const { node } = path
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 { body } = parent.node as t.Program | t.BlockStatement
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 'src/analysis/inlineability'
7
- import type { InlineCandidate } from 'src/analysis/inlineability'
8
- import { isPure } from 'src/analysis/purity'
9
- import { enclosingScopeHasDirectEval, isInsideWith, walkOwnFunctionScope } from 'src/utils/ast'
10
- import { reorderableToStatement } from 'src/utils/evaluation-order'
11
- import { generateLoopLabel } from 'src/utils/loop-lowering'
12
- import { hasAnnexBFunctionAlias, isInStrictContext } from 'src/utils/paths'
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 { callee } = path.node
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 { id } = declPath.node.declarations[0]!
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 { id } = path.node
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 { scope } = stmtParent
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 { name } = parent.node.id
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 { name } = parent.node.left
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 { name } = node
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 'src/analysis/purity'
6
- import { isInsideWith } from 'src/utils/ast'
7
- import { traverseForChanges } from 'src/utils/change-tracking'
8
- import type { ChangeState } from 'src/utils/change-tracking'
9
- import { lowerLogicalWriteStatement } from 'src/utils/logical-lowering'
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 { node } = path
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 { scope } = path
57
+ const scope = path.scope
58
58
  const leftPath = path.get('left')
59
59
  let testSrc: t.Expression
60
60
  let valueSrc: t.Expression