miniread 1.68.0 → 1.70.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/stabilize-nested-bindings → core/fingerprint}/fingerprint-scalar-fields.js +23 -54
- package/dist/{transforms/stabilize-top-level-bindings → core/fingerprint}/serialize-fingerprint-node.js +8 -10
- package/dist/core/stable-naming.d.ts +8 -0
- package/dist/core/stable-naming.js +8 -0
- package/dist/transforms/_generated/manifest.js +17 -0
- package/dist/transforms/_generated/registry.js +6 -0
- package/dist/transforms/preset-stats.json +2 -2
- package/dist/transforms/recommended-transform-order.d.ts +1 -1
- package/dist/transforms/recommended-transform-order.js +8 -0
- package/dist/transforms/rename-regex-source-parameters/manifest.json +12 -0
- package/dist/transforms/rename-regex-source-parameters/rename-regex-source-parameters-transform.d.ts +2 -0
- package/dist/transforms/rename-regex-source-parameters/rename-regex-source-parameters-transform.js +126 -0
- package/dist/transforms/stabilize-deferred-stable-rhs/check-rhs-stability.d.ts +6 -0
- package/dist/transforms/stabilize-deferred-stable-rhs/check-rhs-stability.js +51 -0
- package/dist/transforms/stabilize-deferred-stable-rhs/manifest.json +13 -0
- package/dist/transforms/stabilize-deferred-stable-rhs/stabilize-deferred-stable-rhs-transform.d.ts +2 -0
- package/dist/transforms/stabilize-deferred-stable-rhs/stabilize-deferred-stable-rhs-transform.js +125 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/collect-deferred-variables.d.ts +22 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/collect-deferred-variables.js +115 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/manifest.json +13 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/rename-helpers.d.ts +24 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/rename-helpers.js +92 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/stabilize-deferred-top-level-bindings-transform.d.ts +2 -0
- package/dist/transforms/stabilize-deferred-top-level-bindings/stabilize-deferred-top-level-bindings-transform.js +68 -0
- package/dist/transforms/stabilize-nested-bindings/collect-factory-bindings.js +1 -1
- package/dist/transforms/stabilize-nested-bindings/is-factory-callback.js +1 -5
- package/dist/transforms/stabilize-top-level-bindings/collect-rename-candidates.js +1 -1
- package/package.json +1 -1
- package/dist/transforms/stabilize-nested-bindings/serialize-fingerprint-node.js +0 -102
- package/dist/transforms/stabilize-top-level-bindings/fingerprint-leaf-node.d.ts +0 -2
- package/dist/transforms/stabilize-top-level-bindings/fingerprint-leaf-node.js +0 -23
- package/dist/transforms/stabilize-top-level-bindings/fingerprint-node.d.ts +0 -1
- package/dist/transforms/stabilize-top-level-bindings/fingerprint-node.js +0 -9
- package/dist/transforms/stabilize-top-level-bindings/fingerprint-scalar-fields.d.ts +0 -2
- package/dist/transforms/stabilize-top-level-bindings/fingerprint-scalar-fields.js +0 -153
- package/dist/transforms/stabilize-top-level-bindings/serialize-fingerprint-node.d.ts +0 -3
- /package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/fingerprint-leaf-node.d.ts +0 -0
- /package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/fingerprint-leaf-node.js +0 -0
- /package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/fingerprint-scalar-fields.d.ts +0 -0
- /package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/hash-fingerprint-node.d.ts +0 -0
- /package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/hash-fingerprint-node.js +0 -0
- /package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/serialize-fingerprint-node.d.ts +0 -0
package/dist/{transforms/stabilize-nested-bindings → core/fingerprint}/fingerprint-scalar-fields.js
RENAMED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
2
|
const encodeScalar = (value) => value === undefined ? "undefined" : JSON.stringify(value);
|
|
3
|
+
const extractKeyName = (key) => {
|
|
4
|
+
if (t.isIdentifier(key))
|
|
5
|
+
return key.name;
|
|
6
|
+
if (t.isStringLiteral(key))
|
|
7
|
+
return key.value;
|
|
8
|
+
if (t.isNumericLiteral(key))
|
|
9
|
+
return String(key.value);
|
|
10
|
+
if (t.isPrivateName(key))
|
|
11
|
+
return `#${key.id.name}`;
|
|
12
|
+
return undefined;
|
|
13
|
+
};
|
|
3
14
|
export const fingerprintScalarFields = (node) => {
|
|
4
15
|
if (node.type === "AssignmentExpression" ||
|
|
5
16
|
node.type === "BinaryExpression" ||
|
|
@@ -20,6 +31,9 @@ export const fingerprintScalarFields = (node) => {
|
|
|
20
31
|
const computed = node.computed;
|
|
21
32
|
const property = node
|
|
22
33
|
.property;
|
|
34
|
+
// Include non-computed property names to reduce collisions (e.g. `obj.foo` vs
|
|
35
|
+
// `obj.bar`). This trades some cross-build stability for fewer collisions if
|
|
36
|
+
// a toolchain mangles property names between builds.
|
|
23
37
|
const propertyName = computed === false && t.isIdentifier(property)
|
|
24
38
|
? property.name
|
|
25
39
|
: computed === false && t.isPrivateName(property)
|
|
@@ -47,6 +61,8 @@ export const fingerprintScalarFields = (node) => {
|
|
|
47
61
|
node.type === "ObjectMethod" ||
|
|
48
62
|
node.type === "ClassMethod" ||
|
|
49
63
|
node.type === "ClassPrivateMethod") {
|
|
64
|
+
// Keep a uniform field set for all function-like nodes; some fields (e.g. `static`,
|
|
65
|
+
// `computed`, `kind`) only exist on specific node types and will be `undefined` otherwise.
|
|
50
66
|
const fields = [
|
|
51
67
|
`async=${encodeScalar(node.async)}`,
|
|
52
68
|
`generator=${encodeScalar(node.generator)}`,
|
|
@@ -54,36 +70,13 @@ export const fingerprintScalarFields = (node) => {
|
|
|
54
70
|
`static=${encodeScalar(node.static)}`,
|
|
55
71
|
`computed=${encodeScalar(node.computed)}`,
|
|
56
72
|
];
|
|
57
|
-
if (node.type === "ObjectMethod"
|
|
73
|
+
if (node.type === "ObjectMethod" ||
|
|
74
|
+
node.type === "ClassMethod" ||
|
|
75
|
+
node.type === "ClassPrivateMethod") {
|
|
58
76
|
const computed = node.computed;
|
|
59
77
|
const key = node.key;
|
|
60
78
|
if (computed !== true) {
|
|
61
|
-
|
|
62
|
-
? key.name
|
|
63
|
-
: t.isStringLiteral(key)
|
|
64
|
-
? key.value
|
|
65
|
-
: t.isNumericLiteral(key)
|
|
66
|
-
? String(key.value)
|
|
67
|
-
: t.isPrivateName(key)
|
|
68
|
-
? `#${key.id.name}`
|
|
69
|
-
: undefined;
|
|
70
|
-
fields.push(`keyName=${encodeScalar(keyName)}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (node.type === "ClassMethod" || node.type === "ClassPrivateMethod") {
|
|
74
|
-
const computed = node.computed;
|
|
75
|
-
const key = node.key;
|
|
76
|
-
if (computed !== true) {
|
|
77
|
-
const keyName = t.isIdentifier(key)
|
|
78
|
-
? key.name
|
|
79
|
-
: t.isStringLiteral(key)
|
|
80
|
-
? key.value
|
|
81
|
-
: t.isNumericLiteral(key)
|
|
82
|
-
? String(key.value)
|
|
83
|
-
: t.isPrivateName(key)
|
|
84
|
-
? `#${key.id.name}`
|
|
85
|
-
: undefined;
|
|
86
|
-
fields.push(`keyName=${encodeScalar(keyName)}`);
|
|
79
|
+
fields.push(`keyName=${encodeScalar(extractKeyName(key))}`);
|
|
87
80
|
}
|
|
88
81
|
}
|
|
89
82
|
return fields;
|
|
@@ -93,33 +86,14 @@ export const fingerprintScalarFields = (node) => {
|
|
|
93
86
|
const key = node.key;
|
|
94
87
|
const fields = [`computed=${encodeScalar(computed)}`];
|
|
95
88
|
if (computed !== true) {
|
|
96
|
-
|
|
97
|
-
? key.name
|
|
98
|
-
: t.isStringLiteral(key)
|
|
99
|
-
? key.value
|
|
100
|
-
: t.isNumericLiteral(key)
|
|
101
|
-
? String(key.value)
|
|
102
|
-
: t.isPrivateName(key)
|
|
103
|
-
? `#${key.id.name}`
|
|
104
|
-
: undefined;
|
|
105
|
-
fields.push(`keyName=${encodeScalar(keyName)}`);
|
|
89
|
+
fields.push(`keyName=${encodeScalar(extractKeyName(key))}`);
|
|
106
90
|
}
|
|
107
91
|
return fields;
|
|
108
92
|
}
|
|
109
93
|
if (node.type === "ClassProperty" || node.type === "ClassPrivateProperty") {
|
|
110
94
|
const computed = node.computed;
|
|
111
95
|
const key = node.key;
|
|
112
|
-
const keyName = computed === true
|
|
113
|
-
? undefined
|
|
114
|
-
: t.isIdentifier(key)
|
|
115
|
-
? key.name
|
|
116
|
-
: t.isStringLiteral(key)
|
|
117
|
-
? key.value
|
|
118
|
-
: t.isNumericLiteral(key)
|
|
119
|
-
? String(key.value)
|
|
120
|
-
: t.isPrivateName(key)
|
|
121
|
-
? `#${key.id.name}`
|
|
122
|
-
: undefined;
|
|
96
|
+
const keyName = computed === true ? undefined : extractKeyName(key);
|
|
123
97
|
return [
|
|
124
98
|
`static=${encodeScalar(node.static)}`,
|
|
125
99
|
`computed=${encodeScalar(computed)}`,
|
|
@@ -129,12 +103,7 @@ export const fingerprintScalarFields = (node) => {
|
|
|
129
103
|
if (node.type === "ImportSpecifier") {
|
|
130
104
|
const imported = node
|
|
131
105
|
.imported;
|
|
132
|
-
|
|
133
|
-
? imported.name
|
|
134
|
-
: t.isStringLiteral(imported)
|
|
135
|
-
? imported.value
|
|
136
|
-
: undefined;
|
|
137
|
-
return [`importedName=${encodeScalar(importedName)}`];
|
|
106
|
+
return [`importedName=${encodeScalar(extractKeyName(imported))}`];
|
|
138
107
|
}
|
|
139
108
|
return [];
|
|
140
109
|
};
|
|
@@ -26,17 +26,15 @@ const pushNodeTasks = (stack, node) => {
|
|
|
26
26
|
let visitorKeys = keys;
|
|
27
27
|
// For non-computed member keys, we already serialize `keyName` via scalar fields.
|
|
28
28
|
// Skipping the `key` child keeps fingerprints stable across equivalent key syntax
|
|
29
|
-
// like `{ foo: 1 }` vs `{
|
|
29
|
+
// like `{ foo: 1 }` vs `{ "foo": 1 }`.
|
|
30
30
|
const computed = node.computed;
|
|
31
|
-
if (computed
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
node.type === "ClassProperty" ||
|
|
39
|
-
node.type === "ClassPrivateProperty") {
|
|
31
|
+
if (computed !== true &&
|
|
32
|
+
(node.type === "ObjectProperty" ||
|
|
33
|
+
node.type === "ObjectMethod" ||
|
|
34
|
+
node.type === "ClassMethod" ||
|
|
35
|
+
node.type === "ClassPrivateMethod" ||
|
|
36
|
+
node.type === "ClassProperty" ||
|
|
37
|
+
node.type === "ClassPrivateProperty")) {
|
|
40
38
|
visitorKeys = keys.filter((key) => key !== "key");
|
|
41
39
|
}
|
|
42
40
|
const nodeTasks = [{ kind: "text", text: node.type }];
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* Reserved prefixes:
|
|
8
8
|
* - `$h_`: used by `stabilize-top-level-bindings` for content-hash-based names.
|
|
9
9
|
* - `$f_`: used by `stabilize-nested-bindings` for factory-local content-hash-based names.
|
|
10
|
+
* - `$v_`: used by `stabilize-deferred-top-level-bindings` and `stabilize-deferred-stable-rhs`
|
|
11
|
+
* for deferred variable names derived from enclosing function or RHS hashes.
|
|
10
12
|
*
|
|
11
13
|
* - Stable names (`$timeoutId`): Readable AND deterministic across versions
|
|
12
14
|
* - Readable names (`timeoutId`): Semantic but order-dependent
|
|
@@ -17,6 +19,12 @@ import type { Scope } from "@babel/traverse";
|
|
|
17
19
|
* Transforms should skip variables with this prefix.
|
|
18
20
|
*/
|
|
19
21
|
export declare const isStableRenamed: (name: string) => boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Returns true if the name uses a content-hash-based stable prefix
|
|
24
|
+
* (`$h_`, `$f_`, or `$v_`). Use this to check whether a binding was
|
|
25
|
+
* stabilized by one of the hash-based stabilization transforms.
|
|
26
|
+
*/
|
|
27
|
+
export declare const isHashBasedStableName: (name: string) => boolean;
|
|
20
28
|
/**
|
|
21
29
|
* Entry for a planned rename operation.
|
|
22
30
|
*/
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* Reserved prefixes:
|
|
8
8
|
* - `$h_`: used by `stabilize-top-level-bindings` for content-hash-based names.
|
|
9
9
|
* - `$f_`: used by `stabilize-nested-bindings` for factory-local content-hash-based names.
|
|
10
|
+
* - `$v_`: used by `stabilize-deferred-top-level-bindings` and `stabilize-deferred-stable-rhs`
|
|
11
|
+
* for deferred variable names derived from enclosing function or RHS hashes.
|
|
10
12
|
*
|
|
11
13
|
* - Stable names (`$timeoutId`): Readable AND deterministic across versions
|
|
12
14
|
* - Readable names (`timeoutId`): Semantic but order-dependent
|
|
@@ -21,6 +23,12 @@ const STABLE_PREFIX = "$";
|
|
|
21
23
|
export const isStableRenamed = (name) => {
|
|
22
24
|
return name.startsWith(STABLE_PREFIX);
|
|
23
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if the name uses a content-hash-based stable prefix
|
|
28
|
+
* (`$h_`, `$f_`, or `$v_`). Use this to check whether a binding was
|
|
29
|
+
* stabilized by one of the hash-based stabilization transforms.
|
|
30
|
+
*/
|
|
31
|
+
export const isHashBasedStableName = (name) => name.startsWith("$h_") || name.startsWith("$f_") || name.startsWith("$v_");
|
|
24
32
|
/**
|
|
25
33
|
* Creates a stable name by adding the $ prefix.
|
|
26
34
|
* Internal helper - prefer using RenameGroup which handles stability logic automatically.
|
|
@@ -229,6 +229,10 @@ const manifestData = {
|
|
|
229
229
|
notes: "Measured with baseline none: 0.00%. Added to recommended for readability.",
|
|
230
230
|
evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T20:09:26.721Z", "changedLines": 6, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 100 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T23:27:14.483Z", "changedLines": 6, "durationSeconds": 44.636690875, "stableNames": 1358 } },
|
|
231
231
|
},
|
|
232
|
+
"rename-regex-source-parameters": {
|
|
233
|
+
recommended: true,
|
|
234
|
+
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-05T18:50:18.894Z", "changedLines": 312, "durationSeconds": 224.52329859600002, "stableNames": 1357 } },
|
|
235
|
+
},
|
|
232
236
|
"rename-replace-child-parameters": {
|
|
233
237
|
recommended: false,
|
|
234
238
|
notes: "Measured with baseline none: 0.00%.",
|
|
@@ -334,6 +338,16 @@ const manifestData = {
|
|
|
334
338
|
notes: "Auto-added by evaluation script. Measured with baseline none: -0.28%. Enabled in the recommended preset for readability and to normalize variable declarations even when line diffs increase.",
|
|
335
339
|
evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T20:21:14.926Z", "changedLines": 208592, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 100.27969913444457 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100.27969913444457, "evaluatedAt": "2026-01-25T23:41:19.807Z", "changedLines": 208592, "durationSeconds": 65.61050708399999, "stableNames": 1357 } },
|
|
336
340
|
},
|
|
341
|
+
"stabilize-deferred-stable-rhs": {
|
|
342
|
+
recommended: true,
|
|
343
|
+
notes: "Stabilizes deferred top-level vars whose RHS contains only stable identifiers (globals or $h_/$f_/$v_ prefixed names). Derives names by hashing the RHS code. Complements stabilize-deferred-top-level-bindings by handling multi-var functions.",
|
|
344
|
+
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 95.54, "evaluatedAt": "2026-02-05T18:30:00.000Z", "changedLines": 3730, "durationSeconds": 30, "stableNames": 1741 } },
|
|
345
|
+
},
|
|
346
|
+
"stabilize-deferred-top-level-bindings": {
|
|
347
|
+
recommended: true,
|
|
348
|
+
notes: "Stabilizes top-level var declarations that are initialized inside stable-named functions (lazy init pattern). Only applies when the enclosing function has exactly one such deferred var to avoid order-dependent naming. Renames ~750 vars but diff reduction is minimal (0.03%) because most vars already have consistent minified names between versions. The stabilization helps when minifiers do vary names.",
|
|
349
|
+
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 99.97, "evaluatedAt": "2026-02-05T17:32:00.000Z", "changedLines": 753, "durationSeconds": 26, "stableNames": 2110 } },
|
|
350
|
+
},
|
|
337
351
|
"stabilize-nested-bindings": {
|
|
338
352
|
recommended: true,
|
|
339
353
|
notes: "Stabilizes local bindings inside CommonJS factory callbacks using content-hash naming ($f_<hash>). Must run AFTER stabilize-top-level-bindings. Combined with top-level stabilization, achieves 33.49% diff size (67% reduction from baseline).",
|
|
@@ -377,6 +391,8 @@ export const manifestEntries = Object.entries(transformRegistry)
|
|
|
377
391
|
export const recommendedTransformIds = [
|
|
378
392
|
"stabilize-top-level-bindings",
|
|
379
393
|
"stabilize-nested-bindings",
|
|
394
|
+
"stabilize-deferred-top-level-bindings",
|
|
395
|
+
"stabilize-deferred-stable-rhs",
|
|
380
396
|
"expand-boolean-literals",
|
|
381
397
|
"expand-sequence-expressions-v5",
|
|
382
398
|
"expand-special-number-literals",
|
|
@@ -418,6 +434,7 @@ export const recommendedTransformIds = [
|
|
|
418
434
|
"rename-range-parameters",
|
|
419
435
|
"rename-read-file-lines",
|
|
420
436
|
"rename-regex-builders",
|
|
437
|
+
"rename-regex-source-parameters",
|
|
421
438
|
"rename-search-parameters-variables",
|
|
422
439
|
"rename-string-split-variables",
|
|
423
440
|
"rename-this-aliases",
|
|
@@ -46,6 +46,7 @@ import { renamePromiseExecutorParametersV2Transform } from "../rename-promise-ex
|
|
|
46
46
|
import { renameRangeParametersTransform } from "../rename-range-parameters/rename-range-parameters-transform.js";
|
|
47
47
|
import { renameReadFileLinesTransform } from "../rename-read-file-lines/rename-read-file-lines-transform.js";
|
|
48
48
|
import { renameRegexBuildersTransform } from "../rename-regex-builders/rename-regex-builders-transform.js";
|
|
49
|
+
import { renameRegexSourceParametersTransform } from "../rename-regex-source-parameters/rename-regex-source-parameters-transform.js";
|
|
49
50
|
import { renameReplaceChildParametersTransform } from "../rename-replace-child-parameters/rename-replace-child-parameters-transform.js";
|
|
50
51
|
import { renameRestParametersTransform } from "../rename-rest-parameters/rename-rest-parameters-transform.js";
|
|
51
52
|
import { renameSafePropertyAccessorParametersTransform } from "../rename-safe-property-accessor-parameters/rename-safe-property-accessor-parameters-transform.js";
|
|
@@ -68,6 +69,8 @@ import { replaceDynamicRequireEvalTransform } from "../replace-dynamic-require-e
|
|
|
68
69
|
import { simplifyBooleanNegationsTransform } from "../simplify-boolean-negations/simplify-boolean-negations-transform.js";
|
|
69
70
|
import { simplifyStringTrimTransform } from "../simplify-string-trim/simplify-string-trim-transform.js";
|
|
70
71
|
import { splitVariableDeclarationsTransform } from "../split-variable-declarations/split-variable-declarations-transform.js";
|
|
72
|
+
import { stabilizeDeferredStableRhsTransform } from "../stabilize-deferred-stable-rhs/stabilize-deferred-stable-rhs-transform.js";
|
|
73
|
+
import { stabilizeDeferredTopLevelBindingsTransform } from "../stabilize-deferred-top-level-bindings/stabilize-deferred-top-level-bindings-transform.js";
|
|
71
74
|
import { stabilizeNestedBindingsTransform } from "../stabilize-nested-bindings/stabilize-nested-bindings-transform.js";
|
|
72
75
|
import { stabilizeTopLevelBindingsTransform } from "../stabilize-top-level-bindings/stabilize-top-level-bindings-transform.js";
|
|
73
76
|
import { useObjectPropertyShorthandTransform } from "../use-object-property-shorthand/use-object-property-shorthand-transform.js";
|
|
@@ -120,6 +123,7 @@ export const transformRegistry = {
|
|
|
120
123
|
[renameRangeParametersTransform.id]: renameRangeParametersTransform,
|
|
121
124
|
[renameReadFileLinesTransform.id]: renameReadFileLinesTransform,
|
|
122
125
|
[renameRegexBuildersTransform.id]: renameRegexBuildersTransform,
|
|
126
|
+
[renameRegexSourceParametersTransform.id]: renameRegexSourceParametersTransform,
|
|
123
127
|
[renameReplaceChildParametersTransform.id]: renameReplaceChildParametersTransform,
|
|
124
128
|
[renameRestParametersTransform.id]: renameRestParametersTransform,
|
|
125
129
|
[renameSafePropertyAccessorParametersTransform.id]: renameSafePropertyAccessorParametersTransform,
|
|
@@ -142,6 +146,8 @@ export const transformRegistry = {
|
|
|
142
146
|
[simplifyBooleanNegationsTransform.id]: simplifyBooleanNegationsTransform,
|
|
143
147
|
[simplifyStringTrimTransform.id]: simplifyStringTrimTransform,
|
|
144
148
|
[splitVariableDeclarationsTransform.id]: splitVariableDeclarationsTransform,
|
|
149
|
+
[stabilizeDeferredStableRhsTransform.id]: stabilizeDeferredStableRhsTransform,
|
|
150
|
+
[stabilizeDeferredTopLevelBindingsTransform.id]: stabilizeDeferredTopLevelBindingsTransform,
|
|
145
151
|
[stabilizeNestedBindingsTransform.id]: stabilizeNestedBindingsTransform,
|
|
146
152
|
[stabilizeTopLevelBindingsTransform.id]: stabilizeTopLevelBindingsTransform,
|
|
147
153
|
[useObjectPropertyShorthandTransform.id]: useObjectPropertyShorthandTransform,
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* This lets us tune transform interactions intentionally instead of relying on
|
|
5
5
|
* alphabetical ID sorting.
|
|
6
6
|
*/
|
|
7
|
-
export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-date-now-start-times", "rename-default-options-parameters", "rename-deferred-resolve-parameters", "rename-destructured-aliases", "rename-rest-parameters", "rename-execfile-arguments", "rename-error-first-callback-parameters", "rename-error-variables", "rename-event-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-parameters-to-match-properties-v2", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-search-parameters-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
|
|
7
|
+
export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-date-now-start-times", "rename-default-options-parameters", "rename-deferred-resolve-parameters", "rename-destructured-aliases", "rename-rest-parameters", "rename-execfile-arguments", "rename-error-first-callback-parameters", "rename-error-variables", "rename-event-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-parameters-to-match-properties-v2", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
|
|
@@ -11,6 +11,13 @@ export const recommendedTransformOrder = [
|
|
|
11
11
|
// Run second: stabilizes local bindings inside CommonJS factory callbacks.
|
|
12
12
|
// Depends on stabilize-top-level-bindings having renamed factory wrapper functions to $h_*.
|
|
13
13
|
"stabilize-nested-bindings",
|
|
14
|
+
// Run third: stabilizes top-level vars that are assigned inside stable-named functions.
|
|
15
|
+
// Depends on stabilize-top-level-bindings having renamed enclosing functions to $h_*.
|
|
16
|
+
"stabilize-deferred-top-level-bindings",
|
|
17
|
+
// Run fourth: stabilizes remaining deferred vars whose RHS has only stable identifiers.
|
|
18
|
+
// Depends on stabilize-top-level-bindings and stabilize-deferred-top-level-bindings
|
|
19
|
+
// having renamed identifiers to $h_*/$v_*.
|
|
20
|
+
"stabilize-deferred-stable-rhs",
|
|
14
21
|
"expand-boolean-literals",
|
|
15
22
|
"expand-sequence-expressions-v5",
|
|
16
23
|
"expand-special-number-literals",
|
|
@@ -55,6 +62,7 @@ export const recommendedTransformOrder = [
|
|
|
55
62
|
"rename-range-parameters",
|
|
56
63
|
"rename-read-file-lines",
|
|
57
64
|
"rename-regex-builders",
|
|
65
|
+
"rename-regex-source-parameters",
|
|
58
66
|
"rename-search-parameters-variables",
|
|
59
67
|
"rename-string-split-variables",
|
|
60
68
|
"rename-this-aliases",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommended": true,
|
|
3
|
+
"evaluations": {
|
|
4
|
+
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
|
+
"diffSizePercent": 100,
|
|
6
|
+
"evaluatedAt": "2026-02-05T18:50:18.894Z",
|
|
7
|
+
"changedLines": 312,
|
|
8
|
+
"durationSeconds": 224.52329859600002,
|
|
9
|
+
"stableNames": 1357
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
package/dist/transforms/rename-regex-source-parameters/rename-regex-source-parameters-transform.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { RenameGroup } from "../../core/stable-naming.js";
|
|
3
|
+
import { getFilesToProcess, } from "../../core/types.js";
|
|
4
|
+
import * as t from "@babel/types";
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
7
|
+
const traverse = require("@babel/traverse").default;
|
|
8
|
+
const PARAMETER_BASE_NAME = "pattern";
|
|
9
|
+
const getReturnArgumentFromConsequent = (consequent) => {
|
|
10
|
+
if (t.isReturnStatement(consequent)) {
|
|
11
|
+
if (!consequent.argument)
|
|
12
|
+
return undefined;
|
|
13
|
+
return consequent.argument;
|
|
14
|
+
}
|
|
15
|
+
if (t.isBlockStatement(consequent) && consequent.body.length === 1) {
|
|
16
|
+
const statement = consequent.body[0];
|
|
17
|
+
if (statement && t.isReturnStatement(statement)) {
|
|
18
|
+
if (!statement.argument)
|
|
19
|
+
return undefined;
|
|
20
|
+
return statement.argument;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
};
|
|
25
|
+
const matchesNegatedIdentifier = (test, name) => t.isUnaryExpression(test, { operator: "!" }) &&
|
|
26
|
+
t.isIdentifier(test.argument, { name });
|
|
27
|
+
const matchesTypeofStringCheck = (test, name) => {
|
|
28
|
+
if (!t.isBinaryExpression(test))
|
|
29
|
+
return false;
|
|
30
|
+
if (test.operator !== "===" && test.operator !== "==")
|
|
31
|
+
return false;
|
|
32
|
+
const left = test.left;
|
|
33
|
+
const right = test.right;
|
|
34
|
+
const isTypeofIdentifier = (expression) => t.isUnaryExpression(expression, { operator: "typeof" }) &&
|
|
35
|
+
t.isIdentifier(expression.argument, { name });
|
|
36
|
+
const isStringLiteralString = (expression) => t.isStringLiteral(expression, { value: "string" });
|
|
37
|
+
return ((isTypeofIdentifier(left) && isStringLiteralString(right)) ||
|
|
38
|
+
(isStringLiteralString(left) && isTypeofIdentifier(right)));
|
|
39
|
+
};
|
|
40
|
+
const matchesRegexSourceNormalizer = (path) => {
|
|
41
|
+
if (path.node.params.length !== 1)
|
|
42
|
+
return undefined;
|
|
43
|
+
const parameter = path.node.params[0];
|
|
44
|
+
if (!parameter || !t.isIdentifier(parameter))
|
|
45
|
+
return undefined;
|
|
46
|
+
if (!t.isBlockStatement(path.node.body))
|
|
47
|
+
return undefined;
|
|
48
|
+
const statements = path.node.body.body;
|
|
49
|
+
if (statements.length !== 3)
|
|
50
|
+
return undefined;
|
|
51
|
+
const first = statements[0];
|
|
52
|
+
const second = statements[1];
|
|
53
|
+
const third = statements[2];
|
|
54
|
+
if (!first || !second || !third)
|
|
55
|
+
return undefined;
|
|
56
|
+
if (!t.isIfStatement(first))
|
|
57
|
+
return undefined;
|
|
58
|
+
if (!t.isIfStatement(second))
|
|
59
|
+
return undefined;
|
|
60
|
+
if (!t.isReturnStatement(third))
|
|
61
|
+
return undefined;
|
|
62
|
+
if (first.alternate || second.alternate)
|
|
63
|
+
return undefined;
|
|
64
|
+
if (!matchesNegatedIdentifier(first.test, parameter.name))
|
|
65
|
+
return undefined;
|
|
66
|
+
const firstReturnArgument = getReturnArgumentFromConsequent(first.consequent);
|
|
67
|
+
if (!firstReturnArgument || !t.isNullLiteral(firstReturnArgument)) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
if (!matchesTypeofStringCheck(second.test, parameter.name))
|
|
71
|
+
return undefined;
|
|
72
|
+
const secondReturnArgument = getReturnArgumentFromConsequent(second.consequent);
|
|
73
|
+
if (!secondReturnArgument)
|
|
74
|
+
return undefined;
|
|
75
|
+
if (!t.isIdentifier(secondReturnArgument, { name: parameter.name })) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const finalReturnArgument = third.argument;
|
|
79
|
+
if (!finalReturnArgument)
|
|
80
|
+
return undefined;
|
|
81
|
+
if (!t.isMemberExpression(finalReturnArgument))
|
|
82
|
+
return undefined;
|
|
83
|
+
if (finalReturnArgument.computed)
|
|
84
|
+
return undefined;
|
|
85
|
+
if (!t.isIdentifier(finalReturnArgument.object, { name: parameter.name })) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
if (!t.isIdentifier(finalReturnArgument.property, { name: "source" })) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return { parameterName: parameter.name };
|
|
92
|
+
};
|
|
93
|
+
export const renameRegexSourceParametersTransform = {
|
|
94
|
+
id: "rename-regex-source-parameters",
|
|
95
|
+
description: "Renames regex source normalizer parameters to $pattern when they accept string or RegExp inputs.",
|
|
96
|
+
scope: "file",
|
|
97
|
+
parallelizable: true,
|
|
98
|
+
transform(context) {
|
|
99
|
+
let nodesVisited = 0;
|
|
100
|
+
let transformationsApplied = 0;
|
|
101
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
102
|
+
const group = new RenameGroup();
|
|
103
|
+
traverse(fileInfo.ast, {
|
|
104
|
+
Function(path) {
|
|
105
|
+
nodesVisited++;
|
|
106
|
+
const match = matchesRegexSourceNormalizer(path);
|
|
107
|
+
if (!match)
|
|
108
|
+
return;
|
|
109
|
+
const binding = path.scope.getBinding(match.parameterName);
|
|
110
|
+
if (!binding?.constant)
|
|
111
|
+
return;
|
|
112
|
+
group.add({
|
|
113
|
+
scope: path.scope,
|
|
114
|
+
currentName: match.parameterName,
|
|
115
|
+
baseName: PARAMETER_BASE_NAME,
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
transformationsApplied += group.apply();
|
|
120
|
+
}
|
|
121
|
+
return Promise.resolve({
|
|
122
|
+
nodesVisited,
|
|
123
|
+
transformationsApplied,
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Expression } from "@babel/types";
|
|
2
|
+
/**
|
|
3
|
+
* Check if all identifier references in an expression are stable
|
|
4
|
+
* (globals or already-stabilized names).
|
|
5
|
+
*/
|
|
6
|
+
export declare const hasAllStableReferences: (expression: Expression, programScopeBindings: Set<string>) => boolean;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isHashBasedStableName } from "../../core/stable-naming.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check if all identifier references in an expression are stable
|
|
4
|
+
* (globals or already-stabilized names).
|
|
5
|
+
*/
|
|
6
|
+
export const hasAllStableReferences = (expression, programScopeBindings) => {
|
|
7
|
+
const identifiers = collectIdentifierReferences(expression);
|
|
8
|
+
return identifiers.every((name) => isHashBasedStableName(name) || !programScopeBindings.has(name));
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Collect all identifier references in an expression,
|
|
12
|
+
* skipping non-computed property keys in member expressions and object literals.
|
|
13
|
+
*/
|
|
14
|
+
const collectIdentifierReferences = (node) => {
|
|
15
|
+
if (!node || typeof node !== "object")
|
|
16
|
+
return [];
|
|
17
|
+
const astNode = node;
|
|
18
|
+
if (astNode.type === "Identifier")
|
|
19
|
+
return [astNode.name];
|
|
20
|
+
if ((astNode.type === "MemberExpression" ||
|
|
21
|
+
astNode.type === "OptionalMemberExpression") &&
|
|
22
|
+
!astNode.computed) {
|
|
23
|
+
return collectIdentifierReferences(astNode.object);
|
|
24
|
+
}
|
|
25
|
+
// Skip non-computed, non-shorthand ObjectProperty keys — they're labels, not references.
|
|
26
|
+
if (astNode.type === "ObjectProperty" &&
|
|
27
|
+
!astNode.computed &&
|
|
28
|
+
!astNode.shorthand) {
|
|
29
|
+
return collectIdentifierReferences(astNode.value);
|
|
30
|
+
}
|
|
31
|
+
const result = [];
|
|
32
|
+
for (const [key, value] of Object.entries(astNode)) {
|
|
33
|
+
if (key === "type" || key === "start" || key === "end" || key === "loc")
|
|
34
|
+
continue;
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
for (const item of value) {
|
|
37
|
+
if (item &&
|
|
38
|
+
typeof item === "object" &&
|
|
39
|
+
item.type) {
|
|
40
|
+
result.push(...collectIdentifierReferences(item));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (value &&
|
|
45
|
+
typeof value === "object" &&
|
|
46
|
+
value.type) {
|
|
47
|
+
result.push(...collectIdentifierReferences(value));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommended": true,
|
|
3
|
+
"notes": "Stabilizes deferred top-level vars whose RHS contains only stable identifiers (globals or $h_/$f_/$v_ prefixed names). Derives names by hashing the RHS code. Complements stabilize-deferred-top-level-bindings by handling multi-var functions.",
|
|
4
|
+
"evaluations": {
|
|
5
|
+
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
6
|
+
"diffSizePercent": 95.54,
|
|
7
|
+
"evaluatedAt": "2026-02-05T18:30:00.000Z",
|
|
8
|
+
"changedLines": 3730,
|
|
9
|
+
"durationSeconds": 30,
|
|
10
|
+
"stableNames": 1741
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|