miniread 1.118.1 → 1.119.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 (53) hide show
  1. package/dist/transforms/preset-stats.json +2 -2
  2. package/dist/transforms-by-id/expand-typeof-undefined-comparisons/expand-typeof-undefined-comparisons-transform.js +8 -1
  3. package/dist/transforms-by-id/expand-typeof-undefined-comparisons/manifest.json +5 -5
  4. package/dist/transforms-by-id/expand-typeof-undefined-comparisons/resolve-typeof-equality.js +18 -5
  5. package/dist/transforms-by-id/expand-typeof-undefined-comparisons/resolve-typeof-undefined-comparison.js +10 -3
  6. package/dist/transforms-by-id/rename-awaiter-parameters/awaiter-pattern.js +12 -6
  7. package/dist/transforms-by-id/rename-awaiter-parameters/manifest.json +7 -7
  8. package/dist/transforms-by-id/rename-awaiter-parameters/rename-awaiter-bindings.js +80 -1
  9. package/dist/transforms-by-id/rename-awaiter-parameters/rename-awaiter-parameters-transform.js +3 -3
  10. package/dist/transforms-by-id/rename-buffer-variables/is-allowed-buffer-binding.js +43 -7
  11. package/dist/transforms-by-id/rename-buffer-variables/is-allowed-buffer-factory-call.js +42 -11
  12. package/dist/transforms-by-id/rename-buffer-variables/manifest.json +4 -4
  13. package/dist/transforms-by-id/rename-buffer-variables/rename-buffer-variables-transform.js +30 -9
  14. package/dist/transforms-by-id/rename-default-options-parameters-v3/collect-options-like-reference-signals.d.ts +7 -0
  15. package/dist/transforms-by-id/rename-default-options-parameters-v3/collect-options-like-reference-signals.js +65 -0
  16. package/dist/transforms-by-id/rename-default-options-parameters-v3/manifest.json +3 -3
  17. package/dist/transforms-by-id/rename-default-options-parameters-v3/rename-default-options-parameters-v3-transform.js +14 -26
  18. package/dist/transforms-by-id/rename-fs-sync-variables/manifest.json +5 -5
  19. package/dist/transforms-by-id/rename-fs-sync-variables/rename-fs-sync-variables-transform.js +29 -2
  20. package/dist/transforms-by-id/rename-map-by-id-variables/get-map-by-id-pattern.d.ts +3 -1
  21. package/dist/transforms-by-id/rename-map-by-id-variables/get-map-by-id-pattern.js +56 -37
  22. package/dist/transforms-by-id/rename-map-by-id-variables/manifest.json +4 -4
  23. package/dist/transforms-by-id/rename-map-by-id-variables/rename-map-by-id-variables-transform.js +51 -21
  24. package/dist/transforms-by-id/rename-object-keys-reducer-parameters/is-object-keys-reduce-call.d.ts +3 -1
  25. package/dist/transforms-by-id/rename-object-keys-reducer-parameters/is-object-keys-reduce-call.js +37 -30
  26. package/dist/transforms-by-id/rename-object-keys-reducer-parameters/manifest.json +4 -4
  27. package/dist/transforms-by-id/rename-object-keys-reducer-parameters/rename-object-keys-reducer-parameters-transform.js +8 -4
  28. package/dist/transforms-by-id/rename-timeout-promises/add-assignment-timeout-promise-rename-candidate.d.ts +19 -0
  29. package/dist/transforms-by-id/rename-timeout-promises/add-assignment-timeout-promise-rename-candidate.js +76 -0
  30. package/dist/transforms-by-id/rename-timeout-promises/add-executor-parameter-renames.d.ts +4 -0
  31. package/dist/transforms-by-id/rename-timeout-promises/add-executor-parameter-renames.js +30 -0
  32. package/dist/transforms-by-id/rename-timeout-promises/get-promise-executor-parameters.d.ts +1 -1
  33. package/dist/transforms-by-id/rename-timeout-promises/get-promise-executor-parameters.js +3 -3
  34. package/dist/transforms-by-id/rename-timeout-promises/is-promise-constructor.d.ts +3 -0
  35. package/dist/transforms-by-id/rename-timeout-promises/is-promise-constructor.js +53 -0
  36. package/dist/transforms-by-id/rename-timeout-promises/manifest.json +4 -4
  37. package/dist/transforms-by-id/rename-timeout-promises/rename-timeout-promises-transform.js +18 -79
  38. package/dist/transforms-by-id/rename-timeout-promises/set-timeout-usage.js +0 -3
  39. package/dist/transforms-by-id/rename-url-parameters/manifest.json +4 -4
  40. package/dist/transforms-by-id/rename-url-parameters/rename-url-parameters-transform.js +7 -10
  41. package/dist/transforms-by-id/rename-url-parameters/url-parameter-rename-overlap.d.ts +1 -1
  42. package/dist/transforms-by-id/rename-url-parameters/url-parameter-rename-overlap.js +23 -43
  43. package/dist/transforms-by-id/simplify-boolean-negations/get-negated-static-binary-comparison.d.ts +3 -0
  44. package/dist/transforms-by-id/simplify-boolean-negations/get-negated-static-binary-comparison.js +108 -0
  45. package/dist/transforms-by-id/simplify-boolean-negations/get-simplified-negation-replacement.d.ts +3 -0
  46. package/dist/transforms-by-id/simplify-boolean-negations/get-simplified-negation-replacement.js +90 -0
  47. package/dist/transforms-by-id/simplify-boolean-negations/manifest.json +3 -3
  48. package/dist/transforms-by-id/simplify-boolean-negations/simplify-boolean-negations-transform.js +36 -41
  49. package/dist/transforms-by-id/use-object-shorthand/collect-dynamic-lookup-info.d.ts +8 -0
  50. package/dist/transforms-by-id/use-object-shorthand/collect-dynamic-lookup-info.js +65 -0
  51. package/dist/transforms-by-id/use-object-shorthand/manifest.json +4 -4
  52. package/dist/transforms-by-id/use-object-shorthand/use-object-shorthand-transform.js +13 -5
  53. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "recommended": {
3
- "diffSizePercent": 26.024303586952414,
4
- "notes": "Measured with baseline none: 26.02% of original diff."
3
+ "diffSizePercent": 26.01296443285331,
4
+ "notes": "Measured with baseline none: 26.01% of original diff."
5
5
  }
6
6
  }
@@ -21,7 +21,14 @@ export const expandTypeofUndefinedComparisonsTransform = {
21
21
  nodesVisited++;
22
22
  const strictEquality = getStrictTypeofEquality(path.node);
23
23
  if (strictEquality) {
24
- const replacement = t.binaryExpression(strictEquality.operator, t.cloneNode(strictEquality.typeofExpression, true), t.cloneNode(strictEquality.literal, true));
24
+ const directTarget = strictEquality.literal.value === "undefined"
25
+ ? getDirectUndefinedComparisonTarget(path, strictEquality.typeofExpression)
26
+ : undefined;
27
+ const replacement = t.binaryExpression(strictEquality.operator, directTarget
28
+ ? t.cloneNode(directTarget, true)
29
+ : t.cloneNode(strictEquality.typeofExpression, true), directTarget
30
+ ? getUndefinedExpression(path)
31
+ : t.cloneNode(strictEquality.literal, true));
25
32
  path.replaceWith(replacement);
26
33
  transformationsApplied++;
27
34
  return;
@@ -1,14 +1,14 @@
1
1
  {
2
- "recommended": true,
3
- "recommendedOrder": 100,
4
2
  "notes": "Improves readability by expanding minified typeof comparisons; expected to be diff-neutral.",
5
3
  "evaluations": {
6
4
  "claude-code-2.1.10:claude-code-2.1.11": {
7
5
  "diffSizePercent": 100,
8
- "evaluatedAt": "2026-02-09T07:16:31.721Z",
6
+ "evaluatedAt": "2026-02-22T07:02:45.911Z",
9
7
  "changedLines": 1388,
10
- "durationSeconds": 37.124273,
8
+ "durationSeconds": 187.91025176099998,
11
9
  "stableNames": 1357
12
10
  }
13
- }
11
+ },
12
+ "recommended": true,
13
+ "recommendedOrder": 100
14
14
  }
@@ -7,15 +7,25 @@ const isTypeofExpression = (expression) => isExpression(expression) &&
7
7
  const getStringLiteral = (expression) => {
8
8
  if (!isExpression(expression))
9
9
  return undefined;
10
- if (!t.isStringLiteral(expression))
11
- return undefined;
12
- return expression;
10
+ if (t.isStringLiteral(expression))
11
+ return expression;
12
+ if (t.isTemplateLiteral(expression) &&
13
+ expression.expressions.length === 0 &&
14
+ expression.quasis.length === 1) {
15
+ return t.stringLiteral(expression.quasis[0]?.value.cooked ?? "");
16
+ }
17
+ return undefined;
13
18
  };
14
19
  export const getStrictTypeofEquality = (expression) => {
15
- if (expression.operator !== "==" && expression.operator !== "!=") {
20
+ if (expression.operator !== "==" &&
21
+ expression.operator !== "!=" &&
22
+ expression.operator !== "===" &&
23
+ expression.operator !== "!==") {
16
24
  return undefined;
17
25
  }
18
- const operator = expression.operator === "==" ? "===" : "!==";
26
+ const operator = expression.operator === "==" || expression.operator === "==="
27
+ ? "==="
28
+ : "!==";
19
29
  const leftTypeof = isTypeofExpression(expression.left)
20
30
  ? expression.left
21
31
  : undefined;
@@ -25,6 +35,9 @@ export const getStrictTypeofEquality = (expression) => {
25
35
  const leftLiteral = getStringLiteral(expression.left);
26
36
  const rightLiteral = getStringLiteral(expression.right);
27
37
  if (leftTypeof && rightLiteral) {
38
+ if (expression.operator === "===" || expression.operator === "!==") {
39
+ return undefined;
40
+ }
28
41
  return {
29
42
  typeofExpression: leftTypeof,
30
43
  operator,
@@ -7,10 +7,17 @@ const isTypeofExpression = (expression) => isExpression(expression) &&
7
7
  const getTypeofLiteralValue = (expression) => {
8
8
  if (!isExpression(expression))
9
9
  return undefined;
10
- if (!t.isStringLiteral(expression))
10
+ const literalValue = t.isStringLiteral(expression)
11
+ ? expression.value
12
+ : t.isTemplateLiteral(expression) &&
13
+ expression.expressions.length === 0 &&
14
+ expression.quasis.length === 1
15
+ ? expression.quasis[0]?.value.cooked
16
+ : undefined;
17
+ if (!literalValue)
11
18
  return undefined;
12
- if (expression.value === "u" || expression.value === "undefined") {
13
- return expression.value;
19
+ if (literalValue === "u" || literalValue === "undefined") {
20
+ return literalValue;
14
21
  }
15
22
  return undefined;
16
23
  };
@@ -5,6 +5,13 @@ const isIdentifierParameters = (parameters) => {
5
5
  return parameters.every((parameter) => parameter.type === "Identifier");
6
6
  };
7
7
  const isIdentifierNamed = (node, name) => isIdentifier(node) && node.name === name;
8
+ const isStringLiteralNamed = (node, value) => node?.type === "StringLiteral" && node.value === value;
9
+ const isMemberPropertyNamed = (memberExpression, propertyName) => {
10
+ if (!memberExpression.computed) {
11
+ return isIdentifierNamed(memberExpression.property, propertyName);
12
+ }
13
+ return isStringLiteralNamed(memberExpression.property, propertyName);
14
+ };
8
15
  const isEmptyArrayExpression = (node) => node.elements.length === 0;
9
16
  const isArgumentsFallback = (node, argumentsName) => node.operator === "||" &&
10
17
  isIdentifierNamed(node.left, argumentsName) &&
@@ -14,11 +21,9 @@ const isGeneratorApplyCall = (node, generatorName, thisArgumentName, argumentsNa
14
21
  const callee = node.callee;
15
22
  if (callee.type !== "MemberExpression")
16
23
  return false;
17
- if (callee.computed)
18
- return false;
19
24
  if (!isIdentifierNamed(callee.object, generatorName))
20
25
  return false;
21
- if (!isIdentifierNamed(callee.property, "apply"))
26
+ if (!isMemberPropertyNamed(callee, "apply"))
22
27
  return false;
23
28
  if (node.arguments.length !== 2)
24
29
  return false;
@@ -27,6 +32,9 @@ const isGeneratorApplyCall = (node, generatorName, thisArgumentName, argumentsNa
27
32
  return false;
28
33
  if (!isIdentifierNamed(thisArgument, thisArgumentName))
29
34
  return false;
35
+ if (argumentsValue.type === "ArrayExpression") {
36
+ return isEmptyArrayExpression(argumentsValue);
37
+ }
30
38
  if (argumentsValue.type === "Identifier") {
31
39
  return argumentsValue.name === argumentsName;
32
40
  }
@@ -38,11 +46,9 @@ const isGeneratorMethodCall = (node, generatorName, methodName) => {
38
46
  const callee = node.callee;
39
47
  if (callee.type !== "MemberExpression")
40
48
  return false;
41
- if (callee.computed)
42
- return false;
43
49
  if (!isIdentifierNamed(callee.object, generatorName))
44
50
  return false;
45
- return isIdentifierNamed(callee.property, methodName);
51
+ return isMemberPropertyNamed(callee, methodName);
46
52
  };
47
53
  const isPromiseCtorNewExpression = (node, promiseCtorName) => {
48
54
  const callee = node.callee;
@@ -1,14 +1,14 @@
1
1
  {
2
- "recommended": true,
3
- "recommendedOrder": 100,
4
2
  "notes": "Measured with baseline none: 0.00%. Added to recommended for readability.",
5
3
  "evaluations": {
6
4
  "claude-code-2.1.10:claude-code-2.1.11": {
7
5
  "diffSizePercent": 100,
8
- "evaluatedAt": "2026-02-07T21:09:14.149Z",
9
- "changedLines": 196,
10
- "durationSeconds": 154.025962677,
11
- "stableNames": 1361
6
+ "evaluatedAt": "2026-02-22T10:26:55.132Z",
7
+ "changedLines": 280,
8
+ "durationSeconds": 31.154270667000002,
9
+ "stableNames": 1363
12
10
  }
13
- }
11
+ },
12
+ "recommended": true,
13
+ "recommendedOrder": 100
14
14
  }
@@ -5,6 +5,83 @@ const PARAM_BASE_NAMES = {
5
5
  promiseCtor: "promiseCtor",
6
6
  generator: "generator",
7
7
  };
8
+ const EXECUTOR_PARAM_BASE_NAMES = {
9
+ resolve: "resolve",
10
+ reject: "reject",
11
+ };
12
+ const isPromiseCtorNewExpression = (node, promiseCtorName) => {
13
+ const callee = node.callee;
14
+ if (callee.type === "Identifier") {
15
+ return callee.name === promiseCtorName;
16
+ }
17
+ if (callee.type !== "LogicalExpression")
18
+ return false;
19
+ if (callee.operator !== "||")
20
+ return false;
21
+ if (callee.left.type !== "Identifier")
22
+ return false;
23
+ if (callee.left.name !== promiseCtorName)
24
+ return false;
25
+ const right = callee.right;
26
+ if (right.type !== "AssignmentExpression")
27
+ return false;
28
+ if (right.operator !== "=")
29
+ return false;
30
+ if (right.left.type !== "Identifier")
31
+ return false;
32
+ if (right.left.name !== promiseCtorName)
33
+ return false;
34
+ if (right.right.type !== "Identifier")
35
+ return false;
36
+ return right.right.name === "Promise";
37
+ };
38
+ const renameAwaiterPromiseExecutorParameters = (path, names) => {
39
+ let renamed = 0;
40
+ path.traverse({
41
+ NewExpression(innerPath) {
42
+ if (!isPromiseCtorNewExpression(innerPath.node, names.promiseCtor)) {
43
+ return;
44
+ }
45
+ const argumentPaths = innerPath.get("arguments");
46
+ const firstArgumentPath = argumentPaths[0];
47
+ if (!firstArgumentPath)
48
+ return;
49
+ if (!firstArgumentPath.isFunctionExpression() &&
50
+ !firstArgumentPath.isArrowFunctionExpression()) {
51
+ return;
52
+ }
53
+ const executorPath = firstArgumentPath;
54
+ const [resolveParameter, rejectParameter] = executorPath.node.params;
55
+ if (!resolveParameter || !rejectParameter)
56
+ return;
57
+ if (resolveParameter.type !== "Identifier" ||
58
+ rejectParameter.type !== "Identifier") {
59
+ return;
60
+ }
61
+ const resolveBinding = executorPath.scope.getBinding(resolveParameter.name);
62
+ const rejectBinding = executorPath.scope.getBinding(rejectParameter.name);
63
+ if (!resolveBinding || !rejectBinding)
64
+ return;
65
+ if (resolveBinding.scope !== executorPath.scope ||
66
+ rejectBinding.scope !== executorPath.scope) {
67
+ return;
68
+ }
69
+ const executorRenameGroup = new RenameGroup();
70
+ executorRenameGroup.add({
71
+ scope: executorPath.scope,
72
+ currentName: resolveParameter.name,
73
+ baseName: EXECUTOR_PARAM_BASE_NAMES.resolve,
74
+ });
75
+ executorRenameGroup.add({
76
+ scope: executorPath.scope,
77
+ currentName: rejectParameter.name,
78
+ baseName: EXECUTOR_PARAM_BASE_NAMES.reject,
79
+ });
80
+ renamed += executorRenameGroup.apply();
81
+ },
82
+ });
83
+ return renamed;
84
+ };
8
85
  const renameAwaiterParameters = (path, names) => {
9
86
  const thisArgumentBinding = path.scope.getBinding(names.thisArg);
10
87
  const argumentsBinding = path.scope.getBinding(names.args);
@@ -44,6 +121,8 @@ const renameAwaiterParameters = (path, names) => {
44
121
  currentName: names.generator,
45
122
  baseName: PARAM_BASE_NAMES.generator,
46
123
  });
47
- return group.apply();
124
+ const renamedExecutorParameters = renameAwaiterPromiseExecutorParameters(path, names);
125
+ const renamedAwaiterParameters = group.apply();
126
+ return renamedAwaiterParameters + renamedExecutorParameters;
48
127
  };
49
128
  export { renameAwaiterParameters };
@@ -28,9 +28,9 @@ export const renameAwaiterParametersTransform = {
28
28
  promiseCtor: promiseCtor.name,
29
29
  generator: generator.name,
30
30
  };
31
- if (isStableRenamed(names.thisArg) ||
32
- isStableRenamed(names.args) ||
33
- isStableRenamed(names.promiseCtor) ||
31
+ if (isStableRenamed(names.thisArg) &&
32
+ isStableRenamed(names.args) &&
33
+ isStableRenamed(names.promiseCtor) &&
34
34
  isStableRenamed(names.generator)) {
35
35
  return;
36
36
  }
@@ -89,17 +89,53 @@ const isAllowedBufferModuleRequireBinding = (binding) => {
89
89
  }
90
90
  return propertyPath.isStringLiteral({ value: "Buffer" });
91
91
  };
92
- export const isAllowedBufferNamespaceBinding = (binding) => {
93
- const bindingPath = binding.path;
94
- if (!bindingPath.isImportNamespaceSpecifier()) {
92
+ const isAllowedBufferWrappedRequireNamespaceBinding = (binding) => {
93
+ if (!binding.path.isVariableDeclarator()) {
95
94
  return false;
96
95
  }
97
- const importDeclarationPath = bindingPath.parentPath;
98
- if (!importDeclarationPath.isImportDeclaration()) {
96
+ const idPath = binding.path.get("id");
97
+ if (!idPath.isIdentifier()) {
99
98
  return false;
100
99
  }
101
- const source = importDeclarationPath.node.source.value;
102
- return source === "buffer" || source === "node:buffer";
100
+ const initPath = binding.path.get("init");
101
+ if (Array.isArray(initPath) || !initPath.isCallExpression()) {
102
+ return false;
103
+ }
104
+ if (initPath.node.arguments.length !== 1) {
105
+ return false;
106
+ }
107
+ const [firstArgument] = initPath.node.arguments;
108
+ if (firstArgument?.type !== "CallExpression") {
109
+ return false;
110
+ }
111
+ return isRequireCallOfBufferModule(initPath.get("arguments")[0]);
112
+ };
113
+ const isAllowedBufferModuleRequireNamespaceBinding = (binding) => {
114
+ if (!binding.path.isVariableDeclarator()) {
115
+ return false;
116
+ }
117
+ const idPath = binding.path.get("id");
118
+ if (!idPath.isIdentifier()) {
119
+ return false;
120
+ }
121
+ const initPath = binding.path.get("init");
122
+ if (Array.isArray(initPath)) {
123
+ return false;
124
+ }
125
+ return isRequireCallOfBufferModule(initPath);
126
+ };
127
+ export const isAllowedBufferNamespaceBinding = (binding) => {
128
+ const bindingPath = binding.path;
129
+ if (bindingPath.isImportNamespaceSpecifier()) {
130
+ const importDeclarationPath = bindingPath.parentPath;
131
+ if (!importDeclarationPath.isImportDeclaration()) {
132
+ return false;
133
+ }
134
+ const source = importDeclarationPath.node.source.value;
135
+ return source === "buffer" || source === "node:buffer";
136
+ }
137
+ return (isAllowedBufferModuleRequireNamespaceBinding(binding) ||
138
+ isAllowedBufferWrappedRequireNamespaceBinding(binding));
103
139
  };
104
140
  export const isAllowedBufferBinding = (binding) => {
105
141
  return (isAllowedBufferModuleImportBinding(binding) ||
@@ -13,6 +13,25 @@ const globalBufferNamespaceNames = new Set([
13
13
  "window",
14
14
  "self",
15
15
  ]);
16
+ const isRequireBufferCall = (expression) => {
17
+ if (expression.type !== "CallExpression") {
18
+ return false;
19
+ }
20
+ if (expression.callee.type !== "Identifier") {
21
+ return false;
22
+ }
23
+ if (expression.callee.name !== "require") {
24
+ return false;
25
+ }
26
+ if (expression.arguments.length !== 1) {
27
+ return false;
28
+ }
29
+ const [firstArgument] = expression.arguments;
30
+ if (firstArgument?.type !== "StringLiteral") {
31
+ return false;
32
+ }
33
+ return (firstArgument.value === "buffer" || firstArgument.value === "node:buffer");
34
+ };
16
35
  const getBufferFactoryReceiverIdentifierName = (callExpression) => {
17
36
  const { callee } = callExpression;
18
37
  if (callee.type !== "MemberExpression") {
@@ -28,24 +47,33 @@ const getBufferFactoryReceiverIdentifierName = (callExpression) => {
28
47
  if (receiver.type !== "MemberExpression") {
29
48
  return undefined;
30
49
  }
31
- if (receiver.object.type !== "Identifier") {
32
- return undefined;
33
- }
34
50
  if (!receiver.computed && receiver.property.type === "Identifier") {
35
51
  if (receiver.property.name !== "Buffer")
36
52
  return undefined;
37
- return {
38
- receiverKind: "namespace-buffer-member",
39
- receiverName: receiver.object.name,
40
- };
53
+ if (receiver.object.type === "Identifier") {
54
+ return {
55
+ receiverKind: "namespace-buffer-member",
56
+ receiverName: receiver.object.name,
57
+ };
58
+ }
59
+ if (isRequireBufferCall(receiver.object)) {
60
+ return { receiverKind: "require-buffer-member" };
61
+ }
62
+ return undefined;
41
63
  }
42
64
  if (receiver.computed && receiver.property.type === "StringLiteral") {
43
65
  if (receiver.property.value !== "Buffer")
44
66
  return undefined;
45
- return {
46
- receiverKind: "namespace-buffer-member",
47
- receiverName: receiver.object.name,
48
- };
67
+ if (receiver.object.type === "Identifier") {
68
+ return {
69
+ receiverKind: "namespace-buffer-member",
70
+ receiverName: receiver.object.name,
71
+ };
72
+ }
73
+ if (isRequireBufferCall(receiver.object)) {
74
+ return { receiverKind: "require-buffer-member" };
75
+ }
76
+ return undefined;
49
77
  }
50
78
  return undefined;
51
79
  };
@@ -66,6 +94,9 @@ const hasKnownFactoryName = (callExpression) => {
66
94
  return bufferFactoryNames.has(callee.property.name);
67
95
  };
68
96
  const isAllowedBufferFactoryReceiver = (scope, receiver) => {
97
+ if (receiver.receiverKind === "require-buffer-member") {
98
+ return true;
99
+ }
69
100
  const receiverBinding = scope.getBinding(receiver.receiverName);
70
101
  if (!receiverBinding) {
71
102
  if (receiver.receiverKind === "namespace-buffer-member" &&
@@ -3,10 +3,10 @@
3
3
  "evaluations": {
4
4
  "claude-code-2.1.10:claude-code-2.1.11": {
5
5
  "diffSizePercent": 99.97543183278528,
6
- "evaluatedAt": "2026-02-10T20:28:21.707Z",
7
- "changedLines": 382,
8
- "durationSeconds": 40.716609209000005,
9
- "stableNames": 1359
6
+ "evaluatedAt": "2026-02-22T11:24:48.718Z",
7
+ "changedLines": 644,
8
+ "durationSeconds": 44.056725334,
9
+ "stableNames": 1360
10
10
  }
11
11
  },
12
12
  "recommended": true,
@@ -5,6 +5,24 @@ import { isAllowedBufferFactoryCall } from "./is-allowed-buffer-factory-call.js"
5
5
  const require = createRequire(import.meta.url);
6
6
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7
7
  const traverse = require("@babel/traverse").default;
8
+ const addBufferRenameCandidate = (renameGroup, seenBindings, scope, currentName) => {
9
+ if (isStableRenamed(currentName)) {
10
+ return;
11
+ }
12
+ const binding = scope.getBinding(currentName);
13
+ if (!binding) {
14
+ return;
15
+ }
16
+ if (seenBindings.has(binding)) {
17
+ return;
18
+ }
19
+ seenBindings.add(binding);
20
+ renameGroup.add({
21
+ scope,
22
+ currentName,
23
+ baseName: "buffer",
24
+ });
25
+ };
8
26
  export const renameBufferVariablesTransform = {
9
27
  id: "rename-buffer-variables",
10
28
  description: "Rename variables assigned from Buffer factory calls to buffer",
@@ -15,6 +33,7 @@ export const renameBufferVariablesTransform = {
15
33
  let transformationsApplied = 0;
16
34
  for (const fileInfo of getFilesToProcess(context)) {
17
35
  const renameGroup = new RenameGroup();
36
+ const seenBufferBindings = new WeakSet();
18
37
  traverse(fileInfo.ast, {
19
38
  VariableDeclarator(path) {
20
39
  nodesVisited++;
@@ -25,19 +44,21 @@ export const renameBufferVariablesTransform = {
25
44
  if (!isAllowedBufferFactoryCall(path.scope, init)) {
26
45
  return;
27
46
  }
28
- const currentName = id.name;
29
- if (isStableRenamed(currentName)) {
47
+ addBufferRenameCandidate(renameGroup, seenBufferBindings, path.scope, id.name);
48
+ },
49
+ AssignmentExpression(path) {
50
+ nodesVisited++;
51
+ const { left, operator, right } = path.node;
52
+ if (operator !== "=") {
53
+ return;
54
+ }
55
+ if (left.type !== "Identifier") {
30
56
  return;
31
57
  }
32
- const binding = path.scope.getBinding(currentName);
33
- if (!binding) {
58
+ if (!isAllowedBufferFactoryCall(path.scope, right)) {
34
59
  return;
35
60
  }
36
- renameGroup.add({
37
- scope: path.scope,
38
- currentName,
39
- baseName: "buffer",
40
- });
61
+ addBufferRenameCandidate(renameGroup, seenBufferBindings, path.scope, left.name);
41
62
  },
42
63
  });
43
64
  transformationsApplied += renameGroup.apply();
@@ -0,0 +1,7 @@
1
+ import type { Binding } from "@babel/traverse";
2
+ type OptionsLikeReferenceSignals = {
3
+ allReferencesAreMemberAccesses: boolean;
4
+ destructuredPropertyNames: Set<string>;
5
+ };
6
+ export declare const collectOptionsLikeReferenceSignals: (binding: Binding) => OptionsLikeReferenceSignals;
7
+ export {};
@@ -0,0 +1,65 @@
1
+ export const collectOptionsLikeReferenceSignals = (binding) => {
2
+ const destructuredPropertyNames = new Set();
3
+ const allReferencesAreMemberAccesses = binding.referencePaths.every((referencePath) => isOptionsLikeReference(referencePath, destructuredPropertyNames));
4
+ return { allReferencesAreMemberAccesses, destructuredPropertyNames };
5
+ };
6
+ const isOptionsLikeReference = (referencePath, destructuredPropertyNames) => {
7
+ if (!referencePath.isIdentifier())
8
+ return false;
9
+ let wrappedObject = referencePath.node;
10
+ let parent = referencePath.parentPath;
11
+ while (parent.isTSNonNullExpression() ||
12
+ parent.isTSAsExpression() ||
13
+ parent.isTSTypeAssertion() ||
14
+ parent.isParenthesizedExpression()) {
15
+ wrappedObject = parent.node;
16
+ // Babel type packages differ on whether `parentPath` can be null.
17
+ const nextParent = parent.parentPath;
18
+ if (!nextParent)
19
+ return false;
20
+ parent = nextParent;
21
+ }
22
+ if (parent.isMemberExpression() && parent.node.object === wrappedObject)
23
+ return true;
24
+ if (parent.isOptionalMemberExpression() &&
25
+ parent.node.object === wrappedObject)
26
+ return true;
27
+ if (parent.isVariableDeclarator() &&
28
+ isObjectPatternDestructureOf(parent, wrappedObject)) {
29
+ addObjectPatternPropertyNames(parent.node.id, destructuredPropertyNames);
30
+ return true;
31
+ }
32
+ if (parent.isAssignmentExpression() &&
33
+ isObjectPatternAssignmentOf(parent, wrappedObject)) {
34
+ addObjectPatternPropertyNames(parent.node.left, destructuredPropertyNames);
35
+ return true;
36
+ }
37
+ return false;
38
+ };
39
+ const isObjectPatternDestructureOf = (path, wrappedObject) => {
40
+ if (!path.get("id").isObjectPattern())
41
+ return false;
42
+ return path.node.init === wrappedObject;
43
+ };
44
+ const isObjectPatternAssignmentOf = (path, wrappedObject) => {
45
+ if (!path.get("left").isObjectPattern())
46
+ return false;
47
+ return path.node.right === wrappedObject;
48
+ };
49
+ const addObjectPatternPropertyNames = (pattern, propertyNames) => {
50
+ for (const property of pattern.properties) {
51
+ if (property.type !== "ObjectProperty")
52
+ continue;
53
+ if (property.computed)
54
+ continue;
55
+ if (property.key.type === "Identifier") {
56
+ propertyNames.add(property.key.name);
57
+ }
58
+ else if (property.key.type === "StringLiteral") {
59
+ propertyNames.add(property.key.value);
60
+ }
61
+ if (property.value.type === "ObjectPattern") {
62
+ addObjectPatternPropertyNames(property.value, propertyNames);
63
+ }
64
+ }
65
+ };
@@ -3,9 +3,9 @@
3
3
  "evaluations": {
4
4
  "claude-code-2.1.10:claude-code-2.1.11": {
5
5
  "diffSizePercent": 97.17466077030653,
6
- "evaluatedAt": "2026-02-10T06:08:59.846Z",
7
- "changedLines": 54815,
8
- "durationSeconds": 51.764200458,
6
+ "evaluatedAt": "2026-02-22T11:20:28.909Z",
7
+ "changedLines": 56345,
8
+ "durationSeconds": 45.11951500000001,
9
9
  "stableNames": 1361
10
10
  }
11
11
  },