miniread 1.116.2 → 1.117.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/dist/transforms-by-id/expand-special-number-literals/expand-special-number-literals-transform.js +23 -57
- package/dist/transforms-by-id/expand-special-number-literals/get-special-number-replacement.d.ts +22 -0
- package/dist/transforms-by-id/expand-special-number-literals/get-special-number-replacement.js +66 -0
- package/dist/transforms-by-id/expand-special-number-literals/manifest.json +6 -6
- package/dist/transforms-by-id/rename-charcode-variables-v2/manifest.json +7 -7
- package/dist/transforms-by-id/rename-charcode-variables-v2/rename-charcode-variables-v2-transform.js +13 -0
- package/dist/transforms-by-id/rename-file-extension-variables/manifest.json +6 -6
- package/dist/transforms-by-id/rename-file-extension-variables/match-file-extension-expression.d.ts +2 -0
- package/dist/transforms-by-id/rename-file-extension-variables/match-file-extension-expression.js +145 -0
- package/dist/transforms-by-id/rename-file-extension-variables/rename-file-extension-variables-transform.js +11 -92
- package/dist/transforms-by-id/rename-parameters-to-match-properties-v2/manifest.json +7 -7
- package/dist/transforms-by-id/rename-parameters-to-match-properties-v2/rename-parameters-to-match-properties-v2-transform.js +23 -5
- package/dist/transforms-by-id/rename-regex-builders/manifest.json +7 -7
- package/dist/transforms-by-id/rename-regex-builders/rename-regex-builders-transform.js +53 -4
- package/dist/transforms-by-id/rename-this-aliases/manifest.json +7 -7
- package/dist/transforms-by-id/rename-this-aliases/rename-this-aliases-transform.js +0 -2
- package/dist/transforms-by-id/rename-to-buffer-results/manifest.json +7 -7
- package/dist/transforms-by-id/rename-to-buffer-results/rename-to-buffer-results-transform.js +65 -27
- package/dist/transforms-by-id/rename-use-reference-guards-v2/get-reference-usage.js +6 -2
- package/dist/transforms-by-id/rename-use-reference-guards-v2/is-use-reference-false-initializer.js +2 -0
- package/dist/transforms-by-id/rename-use-reference-guards-v2/manifest.json +7 -7
- package/dist/transforms-by-id/rename-use-reference-guards-v2/rename-use-reference-guards-v2-transform.js +6 -3
- package/dist/transforms-by-id/use-optional-chaining/is-nullish-check.js +19 -1
- package/dist/transforms-by-id/use-optional-chaining/manifest.json +6 -6
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { getFilesToProcess } from "../../core/types.js";
|
|
3
|
+
import { getSpecialNumberReplacement } from "./get-special-number-replacement.js";
|
|
3
4
|
const require = createRequire(import.meta.url);
|
|
4
5
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
5
6
|
const traverse = require("@babel/traverse").default;
|
|
@@ -20,9 +21,6 @@ const containsDirectEval = (container) => {
|
|
|
20
21
|
// bindings into the current function scope (which could shadow `Infinity`/`NaN`
|
|
21
22
|
// and change the meaning of an identifier replacement).
|
|
22
23
|
//
|
|
23
|
-
// Note: Even if `eval` is lexically shadowed, we can't reliably prove statically
|
|
24
|
-
// that it's not bound to the built-in eval at runtime (e.g. `const eval =
|
|
25
|
-
// globalThis.eval`). Be conservative and treat any `eval(...)` call as direct.
|
|
26
24
|
found = true;
|
|
27
25
|
callPath.stop();
|
|
28
26
|
},
|
|
@@ -66,71 +64,39 @@ export const expandSpecialNumberLiteralsTransform = {
|
|
|
66
64
|
traverse(fileInfo.ast, {
|
|
67
65
|
BinaryExpression(path) {
|
|
68
66
|
nodesVisited++;
|
|
69
|
-
|
|
70
|
-
if (operator !== "/")
|
|
67
|
+
if (path.node.operator !== "/")
|
|
71
68
|
return;
|
|
72
|
-
|
|
73
|
-
// brand checks (operator `in`). This guard is just to satisfy the type system.
|
|
74
|
-
if (left.type === "PrivateName")
|
|
69
|
+
if (path.node.left.type === "PrivateName")
|
|
75
70
|
return;
|
|
76
71
|
const leftPath = path.get("left");
|
|
77
72
|
const rightPath = path.get("right");
|
|
78
|
-
// Avoid dropping side effects: `evaluate()` can be confident for expressions that
|
|
79
|
-
// are not pure (e.g. `(foo(), 1) / 0`). Only rewrite when both sides are pure.
|
|
80
|
-
if (!leftPath.isPure() || !rightPath.isPure())
|
|
81
|
-
return;
|
|
82
|
-
const leftEvaluation = leftPath.evaluate();
|
|
83
|
-
if (!leftEvaluation.confident)
|
|
84
|
-
return;
|
|
85
|
-
if (typeof leftEvaluation.value !== "number")
|
|
86
|
-
return;
|
|
87
|
-
const leftValue = leftEvaluation.value;
|
|
88
73
|
const rightEvaluation = rightPath.evaluate();
|
|
89
74
|
if (!rightEvaluation.confident)
|
|
90
75
|
return;
|
|
91
76
|
if (typeof rightEvaluation.value !== "number")
|
|
92
77
|
return;
|
|
93
|
-
|
|
94
|
-
if (!isDivisionByZero(rightValue))
|
|
78
|
+
if (!isDivisionByZero(rightEvaluation.value))
|
|
95
79
|
return;
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (isWithinWithStatement(path))
|
|
114
|
-
return;
|
|
115
|
-
if (isWithinSloppyDirectEvalScope(path))
|
|
116
|
-
return;
|
|
117
|
-
if (path.scope.hasBinding("Infinity", true))
|
|
118
|
-
return;
|
|
119
|
-
path.replaceWith(t.identifier("Infinity"));
|
|
120
|
-
transformationsApplied++;
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (result === -Infinity) {
|
|
124
|
-
if (isWithinWithStatement(path))
|
|
125
|
-
return;
|
|
126
|
-
if (isWithinSloppyDirectEvalScope(path))
|
|
127
|
-
return;
|
|
128
|
-
if (path.scope.hasBinding("Infinity", true))
|
|
129
|
-
return;
|
|
130
|
-
path.replaceWith(t.unaryExpression("-", t.identifier("Infinity")));
|
|
131
|
-
transformationsApplied++;
|
|
80
|
+
const leftEvaluation = leftPath.evaluate();
|
|
81
|
+
const leftValue = leftEvaluation.confident && typeof leftEvaluation.value === "number"
|
|
82
|
+
? leftEvaluation.value
|
|
83
|
+
: undefined;
|
|
84
|
+
const replacement = getSpecialNumberReplacement({
|
|
85
|
+
left: path.node.left,
|
|
86
|
+
leftIsPure: leftPath.isPure(),
|
|
87
|
+
right: path.node.right,
|
|
88
|
+
rightIsPure: rightPath.isPure(),
|
|
89
|
+
rightValue: rightEvaluation.value,
|
|
90
|
+
leftValue,
|
|
91
|
+
path,
|
|
92
|
+
t,
|
|
93
|
+
isWithinWithStatement,
|
|
94
|
+
isWithinSloppyDirectEvalScope,
|
|
95
|
+
});
|
|
96
|
+
if (!replacement)
|
|
132
97
|
return;
|
|
133
|
-
|
|
98
|
+
path.replaceWith(replacement);
|
|
99
|
+
transformationsApplied++;
|
|
134
100
|
},
|
|
135
101
|
});
|
|
136
102
|
}
|
package/dist/transforms-by-id/expand-special-number-literals/get-special-number-replacement.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { BinaryExpression, Expression } from "@babel/types";
|
|
3
|
+
type BabelTypesApi = {
|
|
4
|
+
identifier: (name: string) => Expression;
|
|
5
|
+
unaryExpression: (operator: "-", argument: Expression) => Expression;
|
|
6
|
+
sequenceExpression: (expressions: Expression[]) => Expression;
|
|
7
|
+
binaryExpression: (operator: "*", left: Expression, right: Expression) => Expression;
|
|
8
|
+
};
|
|
9
|
+
type GetSpecialNumberReplacementArguments = {
|
|
10
|
+
left: Expression;
|
|
11
|
+
leftIsPure: boolean;
|
|
12
|
+
right: Expression;
|
|
13
|
+
rightIsPure: boolean;
|
|
14
|
+
rightValue: number;
|
|
15
|
+
leftValue: number | undefined;
|
|
16
|
+
path: NodePath<BinaryExpression>;
|
|
17
|
+
t: BabelTypesApi;
|
|
18
|
+
isWithinWithStatement: (path: NodePath) => boolean;
|
|
19
|
+
isWithinSloppyDirectEvalScope: (path: NodePath) => boolean;
|
|
20
|
+
};
|
|
21
|
+
export declare const getSpecialNumberReplacement: (arguments_: GetSpecialNumberReplacementArguments) => Expression | undefined;
|
|
22
|
+
export {};
|
package/dist/transforms-by-id/expand-special-number-literals/get-special-number-replacement.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const hasUnsafeInfinityScope = (path, isWithinWithStatement, isWithinSloppyDirectEvalScope) => {
|
|
2
|
+
if (isWithinWithStatement(path))
|
|
3
|
+
return true;
|
|
4
|
+
if (isWithinSloppyDirectEvalScope(path))
|
|
5
|
+
return true;
|
|
6
|
+
return path.scope.hasBinding("Infinity", true);
|
|
7
|
+
};
|
|
8
|
+
const hasUnsafeNaNScope = (path, isWithinWithStatement, isWithinSloppyDirectEvalScope) => {
|
|
9
|
+
if (isWithinWithStatement(path))
|
|
10
|
+
return true;
|
|
11
|
+
if (isWithinSloppyDirectEvalScope(path))
|
|
12
|
+
return true;
|
|
13
|
+
return path.scope.hasBinding("NaN", true);
|
|
14
|
+
};
|
|
15
|
+
const createInfinityProduct = (arguments_) => {
|
|
16
|
+
if (Object.is(arguments_.rightValue, -0)) {
|
|
17
|
+
return arguments_.t.binaryExpression("*", arguments_.left, arguments_.t.unaryExpression("-", arguments_.t.identifier("Infinity")));
|
|
18
|
+
}
|
|
19
|
+
return arguments_.t.binaryExpression("*", arguments_.left, arguments_.t.identifier("Infinity"));
|
|
20
|
+
};
|
|
21
|
+
const withSideEffectsPreserved = (arguments_, replacement) => {
|
|
22
|
+
if (arguments_.leftIsPure && arguments_.rightIsPure)
|
|
23
|
+
return replacement;
|
|
24
|
+
const expressions = [];
|
|
25
|
+
if (!arguments_.leftIsPure)
|
|
26
|
+
expressions.push(arguments_.left);
|
|
27
|
+
if (!arguments_.rightIsPure)
|
|
28
|
+
expressions.push(arguments_.right);
|
|
29
|
+
expressions.push(replacement);
|
|
30
|
+
return arguments_.t.sequenceExpression(expressions);
|
|
31
|
+
};
|
|
32
|
+
export const getSpecialNumberReplacement = (arguments_) => {
|
|
33
|
+
if (arguments_.leftValue === undefined) {
|
|
34
|
+
if (!arguments_.leftIsPure)
|
|
35
|
+
return undefined;
|
|
36
|
+
// Replacement still evaluates `left`; skip when `right` has side effects so
|
|
37
|
+
// we do not reorder runtime evaluation from `left`-then-`right` to
|
|
38
|
+
// `right`-then-`left`.
|
|
39
|
+
if (!arguments_.rightIsPure)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (hasUnsafeInfinityScope(arguments_.path, arguments_.isWithinWithStatement, arguments_.isWithinSloppyDirectEvalScope)) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return withSideEffectsPreserved(arguments_, createInfinityProduct(arguments_));
|
|
45
|
+
}
|
|
46
|
+
const result = arguments_.leftValue / arguments_.rightValue;
|
|
47
|
+
if (Number.isNaN(result)) {
|
|
48
|
+
if (hasUnsafeNaNScope(arguments_.path, arguments_.isWithinWithStatement, arguments_.isWithinSloppyDirectEvalScope)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return withSideEffectsPreserved(arguments_, arguments_.t.identifier("NaN"));
|
|
52
|
+
}
|
|
53
|
+
if (result === Infinity) {
|
|
54
|
+
if (hasUnsafeInfinityScope(arguments_.path, arguments_.isWithinWithStatement, arguments_.isWithinSloppyDirectEvalScope)) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return withSideEffectsPreserved(arguments_, arguments_.t.identifier("Infinity"));
|
|
58
|
+
}
|
|
59
|
+
if (result === -Infinity) {
|
|
60
|
+
if (hasUnsafeInfinityScope(arguments_.path, arguments_.isWithinWithStatement, arguments_.isWithinSloppyDirectEvalScope)) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
return withSideEffectsPreserved(arguments_, arguments_.t.unaryExpression("-", arguments_.t.identifier("Infinity")));
|
|
64
|
+
}
|
|
65
|
+
return withSideEffectsPreserved(arguments_, createInfinityProduct(arguments_));
|
|
66
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Auto-added by evaluation script.",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
5
|
"diffSizePercent": 100,
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
6
|
+
"evaluatedAt": "2026-02-21T16:47:56.238Z",
|
|
7
|
+
"changedLines": 314,
|
|
8
|
+
"durationSeconds": 40.9949115,
|
|
11
9
|
"stableNames": 1357
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Derives names from charCodeAt argument for better stability (e.g., $charCodeAtIndex, $charCodeAtIndexPlus1).",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
5
|
"diffSizePercent": 100,
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
11
|
-
"stableNames":
|
|
6
|
+
"evaluatedAt": "2026-02-21T15:11:23.165Z",
|
|
7
|
+
"changedLines": 292,
|
|
8
|
+
"durationSeconds": 192.198072639,
|
|
9
|
+
"stableNames": 1370
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
package/dist/transforms-by-id/rename-charcode-variables-v2/rename-charcode-variables-v2-transform.js
CHANGED
|
@@ -55,6 +55,19 @@ const getArgumentSuffix = (expression, depth = 0) => {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
// Member expression: charCodeAt(cursor.pos) → "Pos"
|
|
59
|
+
if (expression.type === "MemberExpression") {
|
|
60
|
+
if (expression.property.type === "Identifier") {
|
|
61
|
+
return capitalize(expression.property.name);
|
|
62
|
+
}
|
|
63
|
+
if (expression.property.type === "NumericLiteral") {
|
|
64
|
+
if (Number.isInteger(expression.property.value) &&
|
|
65
|
+
expression.property.value >= 0) {
|
|
66
|
+
return String(expression.property.value);
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
58
71
|
return undefined;
|
|
59
72
|
};
|
|
60
73
|
/**
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Measured with baseline none: 100.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-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
6
|
+
"evaluatedAt": "2026-02-21T17:06:33.862Z",
|
|
7
|
+
"changedLines": 40,
|
|
8
|
+
"durationSeconds": 27.991182833,
|
|
11
9
|
"stableNames": 1358
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
package/dist/transforms-by-id/rename-file-extension-variables/match-file-extension-expression.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
const unwrapExpressionWithStringFallback = (expression) => {
|
|
3
|
+
if (!t.isLogicalExpression(expression))
|
|
4
|
+
return undefined;
|
|
5
|
+
if (expression.operator !== "||" && expression.operator !== "??") {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
if (!t.isStringLiteral(expression.right))
|
|
9
|
+
return undefined;
|
|
10
|
+
return expression.left;
|
|
11
|
+
};
|
|
12
|
+
const getMemberPropertyName = (callee) => {
|
|
13
|
+
if (t.isIdentifier(callee.property))
|
|
14
|
+
return callee.property.name;
|
|
15
|
+
if (callee.computed && t.isStringLiteral(callee.property)) {
|
|
16
|
+
return callee.property.value;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
const getCallTarget = (expression, propertyName, argumentsLength) => {
|
|
21
|
+
if (t.isCallExpression(expression)) {
|
|
22
|
+
if (expression.arguments.length !== argumentsLength)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (!t.isMemberExpression(expression.callee))
|
|
25
|
+
return undefined;
|
|
26
|
+
const property = getMemberPropertyName(expression.callee);
|
|
27
|
+
if (property !== propertyName)
|
|
28
|
+
return undefined;
|
|
29
|
+
if (t.isSuper(expression.callee.object))
|
|
30
|
+
return undefined;
|
|
31
|
+
return expression.callee.object;
|
|
32
|
+
}
|
|
33
|
+
if (t.isOptionalCallExpression(expression)) {
|
|
34
|
+
if (expression.arguments.length !== argumentsLength)
|
|
35
|
+
return undefined;
|
|
36
|
+
if (!t.isOptionalMemberExpression(expression.callee))
|
|
37
|
+
return undefined;
|
|
38
|
+
const property = getMemberPropertyName(expression.callee);
|
|
39
|
+
if (property !== propertyName)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (t.isSuper(expression.callee.object))
|
|
42
|
+
return undefined;
|
|
43
|
+
return expression.callee.object;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
};
|
|
47
|
+
const isPathExtnameCall = (expression) => {
|
|
48
|
+
if (!t.isCallExpression(expression) &&
|
|
49
|
+
!t.isOptionalCallExpression(expression)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (expression.arguments.length !== 1)
|
|
53
|
+
return false;
|
|
54
|
+
const callee = expression.callee;
|
|
55
|
+
if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const property = getMemberPropertyName(callee);
|
|
59
|
+
return property === "extname";
|
|
60
|
+
};
|
|
61
|
+
const isSplitDotCall = (expression) => {
|
|
62
|
+
if (!t.isCallExpression(expression) &&
|
|
63
|
+
!t.isOptionalCallExpression(expression)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const splitTarget = getCallTarget(expression, "split", 1);
|
|
67
|
+
if (!splitTarget)
|
|
68
|
+
return false;
|
|
69
|
+
const [delimiter] = expression.arguments;
|
|
70
|
+
if (!delimiter || !t.isStringLiteral(delimiter))
|
|
71
|
+
return false;
|
|
72
|
+
return delimiter.value === ".";
|
|
73
|
+
};
|
|
74
|
+
const getSliceOneTarget = (expression) => {
|
|
75
|
+
const sliceTarget = getCallTarget(expression, "slice", 1);
|
|
76
|
+
if (!sliceTarget)
|
|
77
|
+
return undefined;
|
|
78
|
+
if (!t.isCallExpression(expression) &&
|
|
79
|
+
!t.isOptionalCallExpression(expression)) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
const [sliceStart] = expression.arguments;
|
|
83
|
+
if (!sliceStart || !t.isExpression(sliceStart))
|
|
84
|
+
return undefined;
|
|
85
|
+
if (!t.isNumericLiteral(sliceStart))
|
|
86
|
+
return undefined;
|
|
87
|
+
if (sliceStart.value !== 1)
|
|
88
|
+
return undefined;
|
|
89
|
+
return sliceTarget;
|
|
90
|
+
};
|
|
91
|
+
const isNegativeOne = (expression) => {
|
|
92
|
+
return t.isNumericLiteral(expression)
|
|
93
|
+
? expression.value === -1
|
|
94
|
+
: t.isUnaryExpression(expression) &&
|
|
95
|
+
expression.operator === "-" &&
|
|
96
|
+
t.isNumericLiteral(expression.argument) &&
|
|
97
|
+
expression.argument.value === 1;
|
|
98
|
+
};
|
|
99
|
+
const isSplitAtLastExpression = (expression) => {
|
|
100
|
+
const atTarget = getCallTarget(expression, "at", 1);
|
|
101
|
+
if (!atTarget)
|
|
102
|
+
return false;
|
|
103
|
+
if (!t.isCallExpression(expression) &&
|
|
104
|
+
!t.isOptionalCallExpression(expression)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
const [atIndex] = expression.arguments;
|
|
108
|
+
if (!atIndex || !t.isExpression(atIndex))
|
|
109
|
+
return false;
|
|
110
|
+
if (!isNegativeOne(atIndex))
|
|
111
|
+
return false;
|
|
112
|
+
return isSplitDotCall(atTarget);
|
|
113
|
+
};
|
|
114
|
+
const isPathExtnameDerivedExpression = (expression) => {
|
|
115
|
+
if (isPathExtnameCall(expression))
|
|
116
|
+
return true;
|
|
117
|
+
const lowerTarget = getCallTarget(expression, "toLowerCase", 0);
|
|
118
|
+
if (lowerTarget && isPathExtnameCall(lowerTarget))
|
|
119
|
+
return true;
|
|
120
|
+
const sliceTarget = getSliceOneTarget(expression);
|
|
121
|
+
if (sliceTarget && isPathExtnameCall(sliceTarget))
|
|
122
|
+
return true;
|
|
123
|
+
if (sliceTarget) {
|
|
124
|
+
const lowerBeforeSlice = getCallTarget(sliceTarget, "toLowerCase", 0);
|
|
125
|
+
if (lowerBeforeSlice && isPathExtnameCall(lowerBeforeSlice))
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
if (lowerTarget) {
|
|
129
|
+
const sliceBeforeLower = getSliceOneTarget(lowerTarget);
|
|
130
|
+
if (sliceBeforeLower && isPathExtnameCall(sliceBeforeLower))
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
};
|
|
135
|
+
export const isFileExtensionExpression = (expression) => {
|
|
136
|
+
const normalized = unwrapExpressionWithStringFallback(expression) ?? expression;
|
|
137
|
+
if (isPathExtnameDerivedExpression(normalized))
|
|
138
|
+
return true;
|
|
139
|
+
const lowerTarget = getCallTarget(normalized, "toLowerCase", 0);
|
|
140
|
+
const extractionTarget = lowerTarget ?? normalized;
|
|
141
|
+
const popTarget = getCallTarget(extractionTarget, "pop", 0);
|
|
142
|
+
if (popTarget)
|
|
143
|
+
return isSplitDotCall(popTarget);
|
|
144
|
+
return isSplitAtLastExpression(extractionTarget);
|
|
145
|
+
};
|
|
@@ -2,74 +2,18 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
import * as t from "@babel/types";
|
|
3
3
|
import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
|
|
4
4
|
import { getFilesToProcess } from "../../core/types.js";
|
|
5
|
+
import { isFileExtensionExpression } from "./match-file-extension-expression.js";
|
|
5
6
|
const require = createRequire(import.meta.url);
|
|
6
7
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
7
8
|
const traverse = require("@babel/traverse").default;
|
|
8
|
-
const
|
|
9
|
-
if (
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return expression.left;
|
|
17
|
-
};
|
|
18
|
-
const getMemberPropertyName = (callee) => {
|
|
19
|
-
if (t.isIdentifier(callee.property))
|
|
20
|
-
return callee.property.name;
|
|
21
|
-
if (callee.computed && t.isStringLiteral(callee.property)) {
|
|
22
|
-
return callee.property.value;
|
|
23
|
-
}
|
|
24
|
-
return undefined;
|
|
25
|
-
};
|
|
26
|
-
const getCallTarget = (expression, propertyName, argumentsLength) => {
|
|
27
|
-
if (t.isCallExpression(expression)) {
|
|
28
|
-
if (expression.arguments.length !== argumentsLength)
|
|
29
|
-
return undefined;
|
|
30
|
-
if (!t.isMemberExpression(expression.callee))
|
|
31
|
-
return undefined;
|
|
32
|
-
const property = getMemberPropertyName(expression.callee);
|
|
33
|
-
if (property !== propertyName)
|
|
34
|
-
return undefined;
|
|
35
|
-
if (t.isSuper(expression.callee.object))
|
|
36
|
-
return undefined;
|
|
37
|
-
return expression.callee.object;
|
|
38
|
-
}
|
|
39
|
-
if (t.isOptionalCallExpression(expression)) {
|
|
40
|
-
if (expression.arguments.length !== argumentsLength)
|
|
41
|
-
return undefined;
|
|
42
|
-
if (!t.isOptionalMemberExpression(expression.callee))
|
|
43
|
-
return undefined;
|
|
44
|
-
const property = getMemberPropertyName(expression.callee);
|
|
45
|
-
if (property !== propertyName)
|
|
46
|
-
return undefined;
|
|
47
|
-
if (t.isSuper(expression.callee.object))
|
|
48
|
-
return undefined;
|
|
49
|
-
return expression.callee.object;
|
|
50
|
-
}
|
|
51
|
-
return undefined;
|
|
52
|
-
};
|
|
53
|
-
const isFileExtensionExpression = (expression) => {
|
|
54
|
-
const normalized = unwrapExpressionWithStringFallback(expression);
|
|
55
|
-
if (!normalized)
|
|
56
|
-
return false;
|
|
57
|
-
const lowerTarget = getCallTarget(normalized, "toLowerCase", 0);
|
|
58
|
-
const popTarget = lowerTarget ?? normalized;
|
|
59
|
-
const splitTarget = getCallTarget(popTarget, "pop", 0);
|
|
60
|
-
if (!splitTarget)
|
|
61
|
-
return false;
|
|
62
|
-
const splitCallTarget = getCallTarget(splitTarget, "split", 1);
|
|
63
|
-
if (!splitCallTarget)
|
|
64
|
-
return false;
|
|
65
|
-
if (!t.isCallExpression(splitTarget) &&
|
|
66
|
-
!t.isOptionalCallExpression(splitTarget)) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
const [delimiter] = splitTarget.arguments;
|
|
70
|
-
if (!delimiter || !t.isStringLiteral(delimiter))
|
|
71
|
-
return false;
|
|
72
|
-
return delimiter.value === ".";
|
|
9
|
+
const addRenameCandidate = (currentName, scope, group) => {
|
|
10
|
+
if (isStableRenamed(currentName))
|
|
11
|
+
return;
|
|
12
|
+
group.add({
|
|
13
|
+
scope,
|
|
14
|
+
currentName,
|
|
15
|
+
baseName: "fileExtension",
|
|
16
|
+
});
|
|
73
17
|
};
|
|
74
18
|
const collectFileExtensionParameterRenames = (path, group) => {
|
|
75
19
|
for (const parameter of path.node.params) {
|
|
@@ -79,19 +23,7 @@ const collectFileExtensionParameterRenames = (path, group) => {
|
|
|
79
23
|
continue;
|
|
80
24
|
if (!isFileExtensionExpression(parameter.right))
|
|
81
25
|
continue;
|
|
82
|
-
|
|
83
|
-
if (isStableRenamed(currentName))
|
|
84
|
-
continue;
|
|
85
|
-
if (currentName === "fileExtension")
|
|
86
|
-
continue;
|
|
87
|
-
const binding = path.scope.getBinding(currentName);
|
|
88
|
-
if (!binding?.constant)
|
|
89
|
-
continue;
|
|
90
|
-
group.add({
|
|
91
|
-
scope: path.scope,
|
|
92
|
-
currentName,
|
|
93
|
-
baseName: "fileExtension",
|
|
94
|
-
});
|
|
26
|
+
addRenameCandidate(parameter.left.name, path.scope, group);
|
|
95
27
|
}
|
|
96
28
|
};
|
|
97
29
|
export const renameFileExtensionVariablesTransform = {
|
|
@@ -126,20 +58,7 @@ export const renameFileExtensionVariablesTransform = {
|
|
|
126
58
|
return;
|
|
127
59
|
if (!isFileExtensionExpression(init))
|
|
128
60
|
return;
|
|
129
|
-
|
|
130
|
-
if (isStableRenamed(currentName))
|
|
131
|
-
return;
|
|
132
|
-
if (currentName === "fileExtension")
|
|
133
|
-
return;
|
|
134
|
-
const binding = path.scope.getBinding(currentName);
|
|
135
|
-
if (!binding?.constant)
|
|
136
|
-
return;
|
|
137
|
-
const scope = path.scope;
|
|
138
|
-
group.add({
|
|
139
|
-
scope,
|
|
140
|
-
currentName,
|
|
141
|
-
baseName: "fileExtension",
|
|
142
|
-
});
|
|
61
|
+
addRenameCandidate(id.name, path.scope, group);
|
|
143
62
|
},
|
|
144
63
|
});
|
|
145
64
|
transformationsApplied += group.apply();
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Extends v1 to also handle this.property = param assignments.",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
|
-
"diffSizePercent": 99.
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
5
|
+
"diffSizePercent": 99.99244056393393,
|
|
6
|
+
"evaluatedAt": "2026-02-21T16:50:11.730Z",
|
|
7
|
+
"changedLines": 20517,
|
|
8
|
+
"durationSeconds": 41.078400416,
|
|
11
9
|
"stableNames": 1357
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -5,6 +5,25 @@ import { isStableRenamed } from "../../core/stable-naming.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 hasUnresolvedGlobalReference = (functionPath, name) => {
|
|
9
|
+
let found = false;
|
|
10
|
+
functionPath.traverse({
|
|
11
|
+
Identifier(identifierPath) {
|
|
12
|
+
if (found) {
|
|
13
|
+
identifierPath.skip();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (identifierPath.node.name !== name)
|
|
17
|
+
return;
|
|
18
|
+
if (!identifierPath.isReferencedIdentifier())
|
|
19
|
+
return;
|
|
20
|
+
if (identifierPath.scope.hasBinding(name))
|
|
21
|
+
return;
|
|
22
|
+
found = true;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
return found;
|
|
26
|
+
};
|
|
8
27
|
export const renameParametersToMatchPropertiesV2Transform = {
|
|
9
28
|
id: "rename-parameters-to-match-properties-v2",
|
|
10
29
|
description: "Renames parameters assigned to object properties or this.property",
|
|
@@ -77,11 +96,6 @@ export const renameParametersToMatchPropertiesV2Transform = {
|
|
|
77
96
|
}
|
|
78
97
|
}
|
|
79
98
|
if (candidateName) {
|
|
80
|
-
// Check global references (conservative: if file uses 'console', don't use 'console')
|
|
81
|
-
const programScope = path.scope.getProgramParent();
|
|
82
|
-
if (Object.hasOwn(programScope.globals, candidateName)) {
|
|
83
|
-
isConsistent = false;
|
|
84
|
-
}
|
|
85
99
|
// Check for nested scope shadowing
|
|
86
100
|
// If we rename `a` -> `b`, and a nested scope has `b` bound,
|
|
87
101
|
// and we use `a` in that nested scope, it will become `b` (referring to inner `b`).
|
|
@@ -90,6 +104,10 @@ export const renameParametersToMatchPropertiesV2Transform = {
|
|
|
90
104
|
if (wouldBeShadowed) {
|
|
91
105
|
isConsistent = false;
|
|
92
106
|
}
|
|
107
|
+
if (isConsistent &&
|
|
108
|
+
hasUnresolvedGlobalReference(path, candidateName)) {
|
|
109
|
+
isConsistent = false;
|
|
110
|
+
}
|
|
93
111
|
}
|
|
94
112
|
// Constraints:
|
|
95
113
|
// 1. New name must be valid identifier
|
|
@@ -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-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
11
|
-
"stableNames":
|
|
6
|
+
"evaluatedAt": "2026-02-21T16:55:47.330Z",
|
|
7
|
+
"changedLines": 66,
|
|
8
|
+
"durationSeconds": 33.044639417,
|
|
9
|
+
"stableNames": 1359
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -6,10 +6,24 @@ import { isRegexBuilderObject } from "./is-regex-builder-object.js";
|
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
8
8
|
const traverse = require("@babel/traverse").default;
|
|
9
|
-
const
|
|
9
|
+
const BUILDER_BASE_NAME = "regexBuilder";
|
|
10
|
+
const FACTORY_BASE_NAME = "createRegexBuilder";
|
|
11
|
+
const getReturnedObjectBindingName = (functionPath) => {
|
|
12
|
+
const bodyPath = functionPath.get("body");
|
|
13
|
+
const statements = bodyPath.get("body");
|
|
14
|
+
for (const statementPath of statements) {
|
|
15
|
+
if (!statementPath.isReturnStatement())
|
|
16
|
+
continue;
|
|
17
|
+
const argumentPath = statementPath.get("argument");
|
|
18
|
+
if (!argumentPath.isIdentifier())
|
|
19
|
+
continue;
|
|
20
|
+
return argumentPath.node.name;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
};
|
|
10
24
|
export const renameRegexBuildersTransform = {
|
|
11
25
|
id: "rename-regex-builders",
|
|
12
|
-
description: "Renames fluent regex builder objects
|
|
26
|
+
description: "Renames fluent regex builder objects and their factory functions to stable names.",
|
|
13
27
|
scope: "file",
|
|
14
28
|
parallelizable: true,
|
|
15
29
|
transform(context) {
|
|
@@ -35,12 +49,47 @@ export const renameRegexBuildersTransform = {
|
|
|
35
49
|
return;
|
|
36
50
|
if (!isRegexBuilderObject(initPath, id.name, binding))
|
|
37
51
|
return;
|
|
38
|
-
|
|
52
|
+
group.add({
|
|
53
|
+
scope: path.scope,
|
|
54
|
+
currentName: id.name,
|
|
55
|
+
baseName: BUILDER_BASE_NAME,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
FunctionDeclaration(path) {
|
|
59
|
+
nodesVisited++;
|
|
60
|
+
const id = path.node.id;
|
|
61
|
+
if (!id)
|
|
62
|
+
return;
|
|
63
|
+
if (isStableRenamed(id.name))
|
|
64
|
+
return;
|
|
65
|
+
const functionBinding = path.scope.getBinding(id.name);
|
|
66
|
+
if (!functionBinding)
|
|
67
|
+
return;
|
|
68
|
+
const returnedBindingName = getReturnedObjectBindingName(path);
|
|
69
|
+
if (!returnedBindingName)
|
|
70
|
+
return;
|
|
71
|
+
const returnedBinding = path.scope.getBinding(returnedBindingName);
|
|
72
|
+
if (!returnedBinding)
|
|
73
|
+
return;
|
|
74
|
+
const functionScope = path.get("body").scope;
|
|
75
|
+
if (returnedBinding.scope.getFunctionParent() !== functionScope) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (!returnedBinding.constant)
|
|
79
|
+
return;
|
|
80
|
+
const bindingPath = returnedBinding.path;
|
|
81
|
+
if (!bindingPath.isVariableDeclarator())
|
|
82
|
+
return;
|
|
83
|
+
const initPath = bindingPath.get("init");
|
|
84
|
+
if (!initPath.isObjectExpression())
|
|
85
|
+
return;
|
|
86
|
+
if (!isRegexBuilderObject(initPath, returnedBindingName, returnedBinding)) {
|
|
39
87
|
return;
|
|
88
|
+
}
|
|
40
89
|
group.add({
|
|
41
90
|
scope: path.scope,
|
|
42
91
|
currentName: id.name,
|
|
43
|
-
baseName:
|
|
92
|
+
baseName: FACTORY_BASE_NAME,
|
|
44
93
|
});
|
|
45
94
|
},
|
|
46
95
|
});
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Measured with baseline none: 0.00%. Improves readability by stabilizing `this` aliases used for closures.",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
|
-
"diffSizePercent": 99.
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
5
|
+
"diffSizePercent": 99.99622028196697,
|
|
6
|
+
"evaluatedAt": "2026-02-21T16:46:34.305Z",
|
|
7
|
+
"changedLines": 1729,
|
|
8
|
+
"durationSeconds": 44.609521334,
|
|
11
9
|
"stableNames": 1358
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -31,8 +31,6 @@ export const renameThisAliasesTransform = {
|
|
|
31
31
|
const binding = path.scope.getBinding(currentName);
|
|
32
32
|
if (!binding)
|
|
33
33
|
return;
|
|
34
|
-
if (!binding.constant)
|
|
35
|
-
return;
|
|
36
34
|
if (binding.scope.block.type === "Program" &&
|
|
37
35
|
exportedNames.has(currentName)) {
|
|
38
36
|
return;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"evaluations": {
|
|
5
3
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
6
|
-
"diffSizePercent":
|
|
7
|
-
"evaluatedAt": "2026-02-
|
|
8
|
-
"changedLines":
|
|
9
|
-
"durationSeconds":
|
|
4
|
+
"diffSizePercent": 99.98299126885134,
|
|
5
|
+
"evaluatedAt": "2026-02-21T16:54:10.786Z",
|
|
6
|
+
"changedLines": 392,
|
|
7
|
+
"durationSeconds": 50.692648416000004,
|
|
10
8
|
"stableNames": 1359
|
|
11
9
|
}
|
|
12
|
-
}
|
|
10
|
+
},
|
|
11
|
+
"recommended": true,
|
|
12
|
+
"recommendedOrder": 100
|
|
13
13
|
}
|
package/dist/transforms-by-id/rename-to-buffer-results/rename-to-buffer-results-transform.js
CHANGED
|
@@ -4,6 +4,17 @@ import { getFilesToProcess, } from "../../core/types.js";
|
|
|
4
4
|
const require = createRequire(import.meta.url);
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
6
6
|
const traverse = require("@babel/traverse").default;
|
|
7
|
+
const isBufferFromCall = (callee) => {
|
|
8
|
+
if (callee.type !== "MemberExpression") {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (callee.computed || callee.object.type !== "Identifier") {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return (callee.object.name === "Buffer" &&
|
|
15
|
+
callee.property.type === "Identifier" &&
|
|
16
|
+
callee.property.name === "from");
|
|
17
|
+
};
|
|
7
18
|
const isToBufferCall = (callee) => {
|
|
8
19
|
if (callee.type !== "MemberExpression" &&
|
|
9
20
|
callee.type !== "OptionalMemberExpression") {
|
|
@@ -23,9 +34,51 @@ const isToBufferCall = (callee) => {
|
|
|
23
34
|
}
|
|
24
35
|
return (callee.property.type === "Identifier" && callee.property.name === "toBuffer");
|
|
25
36
|
};
|
|
37
|
+
const isBufferProducingCall = (callExpression) => {
|
|
38
|
+
return (isToBufferCall(callExpression.callee) ||
|
|
39
|
+
(callExpression.type === "CallExpression" &&
|
|
40
|
+
isBufferFromCall(callExpression.callee)));
|
|
41
|
+
};
|
|
42
|
+
const getBufferProducingCallExpression = (expression) => {
|
|
43
|
+
if (expression.type === "CallExpression" ||
|
|
44
|
+
expression.type === "OptionalCallExpression") {
|
|
45
|
+
return isBufferProducingCall(expression) ? expression : undefined;
|
|
46
|
+
}
|
|
47
|
+
if (expression.type !== "AwaitExpression") {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (expression.argument.type !== "CallExpression" &&
|
|
51
|
+
expression.argument.type !== "OptionalCallExpression") {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
return isBufferProducingCall(expression.argument)
|
|
55
|
+
? expression.argument
|
|
56
|
+
: undefined;
|
|
57
|
+
};
|
|
58
|
+
const queueBufferRename = (path, renameGroup, queuedBindings, currentName) => {
|
|
59
|
+
if (isStableRenamed(currentName)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (currentName.toLowerCase().includes("buffer")) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const binding = path.scope.getBinding(currentName);
|
|
66
|
+
if (!binding) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (queuedBindings.has(binding)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
queuedBindings.add(binding);
|
|
73
|
+
renameGroup.add({
|
|
74
|
+
scope: path.scope,
|
|
75
|
+
currentName,
|
|
76
|
+
baseName: "buffer",
|
|
77
|
+
});
|
|
78
|
+
};
|
|
26
79
|
export const renameToBufferResultsTransform = {
|
|
27
80
|
id: "rename-to-buffer-results",
|
|
28
|
-
description: "Renames variables assigned from toBuffer() results to buffer",
|
|
81
|
+
description: "Renames variables assigned from toBuffer()/Buffer.from() results to buffer",
|
|
29
82
|
scope: "file",
|
|
30
83
|
parallelizable: true,
|
|
31
84
|
transform(context) {
|
|
@@ -33,6 +86,7 @@ export const renameToBufferResultsTransform = {
|
|
|
33
86
|
let transformationsApplied = 0;
|
|
34
87
|
for (const fileInfo of getFilesToProcess(context)) {
|
|
35
88
|
const renameGroup = new RenameGroup();
|
|
89
|
+
const queuedBindings = new Set();
|
|
36
90
|
traverse(fileInfo.ast, {
|
|
37
91
|
VariableDeclarator(path) {
|
|
38
92
|
nodesVisited++;
|
|
@@ -40,40 +94,24 @@ export const renameToBufferResultsTransform = {
|
|
|
40
94
|
if (!init || id.type !== "Identifier") {
|
|
41
95
|
return;
|
|
42
96
|
}
|
|
43
|
-
|
|
44
|
-
if (init.type === "CallExpression" ||
|
|
45
|
-
init.type === "OptionalCallExpression") {
|
|
46
|
-
callExpression = init;
|
|
47
|
-
}
|
|
48
|
-
else if (init.type === "AwaitExpression") {
|
|
49
|
-
if (init.argument.type !== "CallExpression" &&
|
|
50
|
-
init.argument.type !== "OptionalCallExpression") {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
callExpression = init.argument;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (!isToBufferCall(callExpression.callee)) {
|
|
97
|
+
if (!getBufferProducingCallExpression(init)) {
|
|
59
98
|
return;
|
|
60
99
|
}
|
|
61
|
-
|
|
62
|
-
|
|
100
|
+
queueBufferRename(path, renameGroup, queuedBindings, id.name);
|
|
101
|
+
},
|
|
102
|
+
AssignmentExpression(path) {
|
|
103
|
+
nodesVisited++;
|
|
104
|
+
const { left, operator, right } = path.node;
|
|
105
|
+
if (operator !== "=") {
|
|
63
106
|
return;
|
|
64
107
|
}
|
|
65
|
-
if (
|
|
108
|
+
if (left.type !== "Identifier") {
|
|
66
109
|
return;
|
|
67
110
|
}
|
|
68
|
-
|
|
69
|
-
if (!binding?.constant) {
|
|
111
|
+
if (!getBufferProducingCallExpression(right)) {
|
|
70
112
|
return;
|
|
71
113
|
}
|
|
72
|
-
renameGroup.
|
|
73
|
-
scope: path.scope,
|
|
74
|
-
currentName,
|
|
75
|
-
baseName: "buffer",
|
|
76
|
-
});
|
|
114
|
+
queueBufferRename(path, renameGroup, queuedBindings, left.name);
|
|
77
115
|
},
|
|
78
116
|
});
|
|
79
117
|
transformationsApplied += renameGroup.apply();
|
|
@@ -2,6 +2,12 @@ import { getMemberExpressionForReference } from "./get-member-expression-for-ref
|
|
|
2
2
|
const getKnownBooleanValue = (expression) => {
|
|
3
3
|
if (expression.type === "BooleanLiteral")
|
|
4
4
|
return expression.value;
|
|
5
|
+
if (expression.type === "NumericLiteral") {
|
|
6
|
+
if (expression.value === 0)
|
|
7
|
+
return false;
|
|
8
|
+
if (expression.value === 1)
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
5
11
|
if (expression.type === "UnaryExpression" &&
|
|
6
12
|
expression.operator === "!" &&
|
|
7
13
|
expression.argument.type === "NumericLiteral" &&
|
|
@@ -33,8 +39,6 @@ export const getReferenceUsage = (binding) => {
|
|
|
33
39
|
return { isSafe: false, hasRead, hasTrueWrite };
|
|
34
40
|
const right = parentPath.node.right;
|
|
35
41
|
const value = getKnownBooleanValue(right);
|
|
36
|
-
if (value === undefined)
|
|
37
|
-
return { isSafe: false, hasRead, hasTrueWrite };
|
|
38
42
|
if (value) {
|
|
39
43
|
hasTrueWrite = true;
|
|
40
44
|
}
|
package/dist/transforms-by-id/rename-use-reference-guards-v2/is-use-reference-false-initializer.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const isKnownFalseValue = (expression) => {
|
|
2
2
|
if (expression.type === "BooleanLiteral")
|
|
3
3
|
return !expression.value;
|
|
4
|
+
if (expression.type === "NumericLiteral")
|
|
5
|
+
return expression.value === 0;
|
|
4
6
|
if (expression.type === "UnaryExpression" &&
|
|
5
7
|
expression.operator === "!" &&
|
|
6
8
|
expression.argument.type === "NumericLiteral" &&
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Supersedes rename-use-reference-guards and also covers guards that reset to false.",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
5
|
"diffSizePercent": 100,
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
11
|
-
"stableNames":
|
|
6
|
+
"evaluatedAt": "2026-02-21T16:41:17.818Z",
|
|
7
|
+
"changedLines": 202,
|
|
8
|
+
"durationSeconds": 34.530502708,
|
|
9
|
+
"stableNames": 1359
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -7,9 +7,10 @@ const require = createRequire(import.meta.url);
|
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
8
8
|
const traverse = require("@babel/traverse").default;
|
|
9
9
|
const BASE_NAME = "hasRunRef";
|
|
10
|
+
const SAFE_READ_ONLY_BASE_NAME = "guardRef";
|
|
10
11
|
const renameUseReferenceGuardsV2Transform = {
|
|
11
12
|
id: "rename-use-reference-guards-v2",
|
|
12
|
-
description: "Renames
|
|
13
|
+
description: "Renames safe useRef(false) guard variables: true-write guards to $hasRunRef/$hasRunRef2/... and read-only/false-only guards to $guardRef/$guardRef2/...",
|
|
13
14
|
scope: "file",
|
|
14
15
|
parallelizable: true,
|
|
15
16
|
transform(context) {
|
|
@@ -34,12 +35,14 @@ const renameUseReferenceGuardsV2Transform = {
|
|
|
34
35
|
return;
|
|
35
36
|
const usage = getReferenceUsage(binding);
|
|
36
37
|
// Unlike v1, this version also accepts guards that reset to false
|
|
37
|
-
if (!usage.isSafe
|
|
38
|
+
if (!usage.isSafe)
|
|
39
|
+
return;
|
|
40
|
+
if (!usage.hasRead)
|
|
38
41
|
return;
|
|
39
42
|
group.add({
|
|
40
43
|
scope: path.scope,
|
|
41
44
|
currentName: id.name,
|
|
42
|
-
baseName: BASE_NAME,
|
|
45
|
+
baseName: usage.hasTrueWrite ? BASE_NAME : SAFE_READ_ONLY_BASE_NAME,
|
|
43
46
|
});
|
|
44
47
|
},
|
|
45
48
|
});
|
|
@@ -14,7 +14,8 @@ const mergeCoverage = (left, right) => {
|
|
|
14
14
|
const getNullishCoverage = (test, identifierName) => {
|
|
15
15
|
const unwrapped = unwrapParentheses(test);
|
|
16
16
|
if (isBinaryExpression(unwrapped)) {
|
|
17
|
-
|
|
17
|
+
const operator = unwrapped.operator;
|
|
18
|
+
if (operator !== "===" && operator !== "==")
|
|
18
19
|
return noCoverage;
|
|
19
20
|
const getValueCoverage = (value) => {
|
|
20
21
|
if (isPrivateName(value))
|
|
@@ -32,6 +33,23 @@ const getNullishCoverage = (test, identifierName) => {
|
|
|
32
33
|
const right = unwrapped.right;
|
|
33
34
|
if (isPrivateName(left))
|
|
34
35
|
return noCoverage;
|
|
36
|
+
if (operator === "==") {
|
|
37
|
+
if (isIdentifier(left) && left.name === identifierName) {
|
|
38
|
+
const valueCoverage = getValueCoverage(right);
|
|
39
|
+
if (valueCoverage.coversNull) {
|
|
40
|
+
return { coversNull: true, coversUndefined: true };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!isPrivateName(right) &&
|
|
44
|
+
isIdentifier(right) &&
|
|
45
|
+
right.name === identifierName) {
|
|
46
|
+
const valueCoverage = getValueCoverage(left);
|
|
47
|
+
if (valueCoverage.coversNull) {
|
|
48
|
+
return { coversNull: true, coversUndefined: true };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return noCoverage;
|
|
52
|
+
}
|
|
35
53
|
if (isIdentifier(left) && left.name === identifierName) {
|
|
36
54
|
return getValueCoverage(right);
|
|
37
55
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"evaluations": {
|
|
5
3
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
6
4
|
"diffSizePercent": 100,
|
|
7
|
-
"evaluatedAt": "2026-02-
|
|
8
|
-
"changedLines":
|
|
9
|
-
"durationSeconds":
|
|
5
|
+
"evaluatedAt": "2026-02-21T16:46:18.553Z",
|
|
6
|
+
"changedLines": 614,
|
|
7
|
+
"durationSeconds": 40.285438,
|
|
10
8
|
"stableNames": 1357
|
|
11
9
|
}
|
|
12
|
-
}
|
|
10
|
+
},
|
|
11
|
+
"recommended": true,
|
|
12
|
+
"recommendedOrder": 100
|
|
13
13
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "miniread",
|
|
3
3
|
"author": "Łukasz Jerciński",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.117.0",
|
|
6
6
|
"description": "Transform minified JavaScript/TypeScript into a more readable form using deterministic AST-based transforms.",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|