miniread 1.9.0 → 1.10.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 (24) hide show
  1. package/dist/scripts/snapshot/run-snapshot-cli.js +58 -69
  2. package/dist/transforms/rename-replace-child-parameters/ast-node-predicates.d.ts +3 -0
  3. package/dist/transforms/rename-replace-child-parameters/ast-node-predicates.js +12 -0
  4. package/dist/transforms/rename-replace-child-parameters/collect-replace-child-parameter-renames.d.ts +3 -0
  5. package/dist/transforms/rename-replace-child-parameters/collect-replace-child-parameter-renames.js +39 -0
  6. package/dist/transforms/rename-replace-child-parameters/constants.d.ts +3 -0
  7. package/dist/transforms/rename-replace-child-parameters/constants.js +3 -0
  8. package/dist/transforms/rename-replace-child-parameters/get-single-return-identifier-name.d.ts +2 -0
  9. package/dist/transforms/rename-replace-child-parameters/get-single-return-identifier-name.js +23 -0
  10. package/dist/transforms/rename-replace-child-parameters/get-two-identifier-parameters.d.ts +6 -0
  11. package/dist/transforms/rename-replace-child-parameters/get-two-identifier-parameters.js +13 -0
  12. package/dist/transforms/rename-replace-child-parameters/has-replace-child-forwarding-call.d.ts +2 -0
  13. package/dist/transforms/rename-replace-child-parameters/has-replace-child-forwarding-call.js +57 -0
  14. package/dist/transforms/rename-replace-child-parameters/is-already-child-parameter-name.d.ts +1 -0
  15. package/dist/transforms/rename-replace-child-parameters/is-already-child-parameter-name.js +8 -0
  16. package/dist/transforms/rename-replace-child-parameters/is-replace-child-named-function.d.ts +2 -0
  17. package/dist/transforms/rename-replace-child-parameters/is-replace-child-named-function.js +43 -0
  18. package/dist/transforms/rename-replace-child-parameters/rename-replace-child-parameters-transform.d.ts +2 -0
  19. package/dist/transforms/rename-replace-child-parameters/rename-replace-child-parameters-transform.js +44 -0
  20. package/dist/transforms/rename-replace-child-parameters/replace-child-types.d.ts +3 -0
  21. package/dist/transforms/rename-replace-child-parameters/replace-child-types.js +1 -0
  22. package/dist/transforms/transform-registry.js +2 -0
  23. package/package.json +1 -1
  24. package/transform-manifest.json +10 -0
@@ -70,24 +70,11 @@ export const runSnapshotCli = async (argv) => {
70
70
  }
71
71
  const expectedPath = path.join(testCaseDirectory, `${transform}-expected.js`);
72
72
  const actualPath = path.join(testCaseDirectory, `${transform}.js`);
73
- // Run the transform and format
74
- let actualOutput;
75
- try {
76
- const rawOutput = await runTransform(basePath, transform);
77
- actualOutput = await formatCode(rawOutput);
78
- }
79
- catch (error) {
80
- const message = error instanceof Error ? error.message : String(error);
81
- console.error(`Error running transform: ${message}`);
82
- return 1;
83
- }
84
73
  if (expected) {
85
74
  // Expected-file workflow
86
75
  // Step 1: Check if expected file exists, create from base.js if not
87
- let expectedExists = false;
88
76
  try {
89
77
  await fs.access(expectedPath);
90
- expectedExists = true;
91
78
  }
92
79
  catch {
93
80
  // Expected file doesn't exist, create it from base.js
@@ -96,67 +83,69 @@ export const runSnapshotCli = async (argv) => {
96
83
  await fs.writeFile(expectedPath, formattedBase);
97
84
  console.log(`Created: test-cases/${testcase}/${transform}-expected.js`);
98
85
  console.log("Edit this file to match your expected output, then re-run.");
99
- }
100
- // Step 2: Write actual output
101
- await fs.writeFile(actualPath, actualOutput);
102
- console.log(`Created: test-cases/${testcase}/${transform}.js`);
103
- if (!expectedExists) {
104
- // First run - just created expected file, user needs to edit it
105
- return 0;
106
- }
107
- // Step 3: Compare expected vs actual
108
- const expectedContent = await fs.readFile(expectedPath, "utf8");
109
- if (expectedContent === actualOutput) {
110
- // Success! Delete expected file
111
- await fs.unlink(expectedPath);
112
- console.log(`\nSuccess: Output matches expected.`);
113
- console.log(`Deleted: test-cases/${testcase}/${transform}-expected.js`);
114
- console.log(`\nSnapshot ready: test-cases/${testcase}/${transform}.js`);
115
86
  return 0;
116
87
  }
117
- else {
118
- // Diff - show the difference
119
- console.log(`\nDiff: expected vs actual`);
120
- console.log("---");
121
- // Simple line-by-line diff output
122
- const expectedLines = expectedContent.split("\n");
123
- const actualLines = actualOutput.split("\n");
124
- const maxLines = Math.max(expectedLines.length, actualLines.length);
125
- let hasDiff = false;
126
- for (let lineIndex = 0; lineIndex < maxLines; lineIndex++) {
127
- const exp = expectedLines[lineIndex];
128
- const act = actualLines[lineIndex];
129
- if (exp !== act) {
130
- hasDiff = true;
131
- if (exp !== undefined && act === undefined) {
132
- console.log(`Line ${lineIndex + 1}:`);
133
- console.log(` - ${exp}`);
134
- }
135
- else if (exp === undefined && act !== undefined) {
136
- console.log(`Line ${lineIndex + 1}:`);
137
- console.log(` + ${act}`);
138
- }
139
- else {
140
- console.log(`Line ${lineIndex + 1}:`);
141
- console.log(` - ${exp}`);
142
- console.log(` + ${act}`);
143
- }
144
- }
88
+ }
89
+ // Common path: Run the transform, format, and write actual output
90
+ let actualOutput;
91
+ try {
92
+ const rawOutput = await runTransform(basePath, transform);
93
+ actualOutput = await formatCode(rawOutput);
94
+ }
95
+ catch (error) {
96
+ const message = error instanceof Error ? error.message : String(error);
97
+ console.error(`Error running transform: ${message}`);
98
+ return 1;
99
+ }
100
+ await fs.writeFile(actualPath, actualOutput);
101
+ console.log(`Created: test-cases/${testcase}/${transform}.js`);
102
+ if (!expected) {
103
+ return 0;
104
+ }
105
+ // Step 3: Compare expected vs actual
106
+ const expectedContent = await fs.readFile(expectedPath, "utf8");
107
+ if (expectedContent === actualOutput) {
108
+ // Success! Delete expected file
109
+ await fs.unlink(expectedPath);
110
+ console.log(`\nSuccess: Output matches expected.`);
111
+ console.log(`Deleted: test-cases/${testcase}/${transform}-expected.js`);
112
+ console.log(`\nSnapshot ready: test-cases/${testcase}/${transform}.js`);
113
+ return 0;
114
+ }
115
+ // Diff - show the difference
116
+ console.log(`\nDiff: expected vs actual`);
117
+ console.log("---");
118
+ // Simple line-by-line diff output
119
+ const expectedLines = expectedContent.split("\n");
120
+ const actualLines = actualOutput.split("\n");
121
+ const maxLines = Math.max(expectedLines.length, actualLines.length);
122
+ let hasDiff = false;
123
+ for (let lineIndex = 0; lineIndex < maxLines; lineIndex++) {
124
+ const exp = expectedLines[lineIndex];
125
+ const act = actualLines[lineIndex];
126
+ if (exp !== act) {
127
+ hasDiff = true;
128
+ if (exp !== undefined && act === undefined) {
129
+ console.log(`Line ${lineIndex + 1}:`);
130
+ console.log(` - ${exp}`);
145
131
  }
146
- if (!hasDiff) {
147
- // Shouldn't happen since we already checked equality, but just in case
148
- console.log("(no visible differences)");
132
+ else if (exp === undefined && act !== undefined) {
133
+ console.log(`Line ${lineIndex + 1}:`);
134
+ console.log(` + ${act}`);
135
+ }
136
+ else {
137
+ console.log(`Line ${lineIndex + 1}:`);
138
+ console.log(` - ${exp}`);
139
+ console.log(` + ${act}`);
149
140
  }
150
- console.log("---");
151
- console.log(`\nExpected file preserved: test-cases/${testcase}/${transform}-expected.js`);
152
- console.log("Fix the implementation or update the expected file, then re-run.");
153
- return 1;
154
141
  }
155
142
  }
156
- else {
157
- // Simple mode: just write actual output
158
- await fs.writeFile(actualPath, actualOutput);
159
- console.log(`Created: test-cases/${testcase}/${transform}.js`);
160
- return 0;
143
+ if (!hasDiff) {
144
+ // Shouldn't happen since we already checked equality, but just in case
145
+ console.log("(no visible differences)");
161
146
  }
147
+ console.log("---");
148
+ console.log(`\nExpected file preserved: test-cases/${testcase}/${transform}-expected.js`);
149
+ console.log("Fix the implementation or update the expected file, then re-run.");
150
+ return 1;
162
151
  };
@@ -0,0 +1,3 @@
1
+ import type { Identifier, StringLiteral } from "@babel/types";
2
+ export declare const isIdentifierNamed: (node: unknown, name: string) => node is Identifier;
3
+ export declare const isStringLiteralValue: (node: unknown, value: string) => node is StringLiteral;
@@ -0,0 +1,12 @@
1
+ export const isIdentifierNamed = (node, name) => {
2
+ return (typeof node === "object" &&
3
+ node !== null &&
4
+ node.type === "Identifier" &&
5
+ node.name === name);
6
+ };
7
+ export const isStringLiteralValue = (node, value) => {
8
+ return (typeof node === "object" &&
9
+ node !== null &&
10
+ node.type === "StringLiteral" &&
11
+ node.value === value);
12
+ };
@@ -0,0 +1,3 @@
1
+ import type { RenameGroup } from "../../core/stable-naming.js";
2
+ import type { ReplaceChildFunctionPath } from "./replace-child-types.js";
3
+ export declare const collectReplaceChildParameterRenames: (path: ReplaceChildFunctionPath, group: RenameGroup) => void;
@@ -0,0 +1,39 @@
1
+ import { isStableRenamed } from "../../core/stable-naming.js";
2
+ import { BASE_NEW_CHILD, BASE_OLD_CHILD } from "./constants.js";
3
+ import { getSingleReturnIdentifierName } from "./get-single-return-identifier-name.js";
4
+ import { getTwoIdentifierParameters } from "./get-two-identifier-parameters.js";
5
+ import { hasReplaceChildForwardingCall } from "./has-replace-child-forwarding-call.js";
6
+ import { isAlreadyChildParameterName } from "./is-already-child-parameter-name.js";
7
+ import { isReplaceChildNamedFunction } from "./is-replace-child-named-function.js";
8
+ export const collectReplaceChildParameterRenames = (path, group) => {
9
+ if (!isReplaceChildNamedFunction(path))
10
+ return;
11
+ if (path.node.body.type !== "BlockStatement")
12
+ return;
13
+ const parameters = getTwoIdentifierParameters(path);
14
+ if (!parameters)
15
+ return;
16
+ const returnIdentifierName = getSingleReturnIdentifierName(path);
17
+ if (returnIdentifierName !== parameters.parameter1.name)
18
+ return;
19
+ if (!hasReplaceChildForwardingCall(path, parameters.parameter0.name, parameters.parameter1.name))
20
+ return;
21
+ const parameter0Name = parameters.parameter0.name;
22
+ if (!isStableRenamed(parameter0Name) &&
23
+ !isAlreadyChildParameterName(parameter0Name, BASE_NEW_CHILD)) {
24
+ group.add({
25
+ scope: path.scope,
26
+ currentName: parameter0Name,
27
+ baseName: BASE_NEW_CHILD,
28
+ });
29
+ }
30
+ const parameter1Name = parameters.parameter1.name;
31
+ if (!isStableRenamed(parameter1Name) &&
32
+ !isAlreadyChildParameterName(parameter1Name, BASE_OLD_CHILD)) {
33
+ group.add({
34
+ scope: path.scope,
35
+ currentName: parameter1Name,
36
+ baseName: BASE_OLD_CHILD,
37
+ });
38
+ }
39
+ };
@@ -0,0 +1,3 @@
1
+ export declare const REPLACE_CHILD_NAME = "replaceChild";
2
+ export declare const BASE_NEW_CHILD = "newChild";
3
+ export declare const BASE_OLD_CHILD = "oldChild";
@@ -0,0 +1,3 @@
1
+ export const REPLACE_CHILD_NAME = "replaceChild";
2
+ export const BASE_NEW_CHILD = "newChild";
3
+ export const BASE_OLD_CHILD = "oldChild";
@@ -0,0 +1,2 @@
1
+ import type { ReplaceChildFunctionPath } from "./replace-child-types.js";
2
+ export declare const getSingleReturnIdentifierName: (path: ReplaceChildFunctionPath) => string | undefined;
@@ -0,0 +1,23 @@
1
+ export const getSingleReturnIdentifierName = (path) => {
2
+ let returnCount = 0;
3
+ let identifierName;
4
+ const rootNode = path.node;
5
+ path.traverse({
6
+ Function(innerPath) {
7
+ if (innerPath.node !== rootNode)
8
+ innerPath.skip();
9
+ },
10
+ ReturnStatement(returnPath) {
11
+ returnCount++;
12
+ const argument = returnPath.node.argument;
13
+ if (argument?.type !== "Identifier") {
14
+ identifierName = undefined;
15
+ return;
16
+ }
17
+ identifierName = argument.name;
18
+ },
19
+ });
20
+ if (returnCount !== 1)
21
+ return;
22
+ return identifierName;
23
+ };
@@ -0,0 +1,6 @@
1
+ import type { Identifier } from "@babel/types";
2
+ import type { ReplaceChildFunctionPath } from "./replace-child-types.js";
3
+ export declare const getTwoIdentifierParameters: (path: ReplaceChildFunctionPath) => {
4
+ parameter0: Identifier;
5
+ parameter1: Identifier;
6
+ } | undefined;
@@ -0,0 +1,13 @@
1
+ export const getTwoIdentifierParameters = (path) => {
2
+ if (path.node.params.length !== 2)
3
+ return;
4
+ const parameter0 = path.node.params[0];
5
+ const parameter1 = path.node.params[1];
6
+ if (parameter0?.type !== "Identifier")
7
+ return;
8
+ if (parameter1?.type !== "Identifier")
9
+ return;
10
+ if (parameter0.name === parameter1.name)
11
+ return;
12
+ return { parameter0, parameter1 };
13
+ };
@@ -0,0 +1,2 @@
1
+ import type { ReplaceChildFunctionPath } from "./replace-child-types.js";
2
+ export declare const hasReplaceChildForwardingCall: (path: ReplaceChildFunctionPath, parameter0Name: string, parameter1Name: string) => boolean;
@@ -0,0 +1,57 @@
1
+ import { isIdentifierNamed } from "./ast-node-predicates.js";
2
+ import { REPLACE_CHILD_NAME } from "./constants.js";
3
+ export const hasReplaceChildForwardingCall = (path, parameter0Name, parameter1Name) => {
4
+ let found = false;
5
+ const rootNode = path.node;
6
+ path.traverse({
7
+ Function(innerPath) {
8
+ if (innerPath.node !== rootNode)
9
+ innerPath.skip();
10
+ },
11
+ CallExpression(callPath) {
12
+ if (found)
13
+ return;
14
+ const call = callPath.node;
15
+ const callee = call.callee;
16
+ if (callee.type !== "MemberExpression")
17
+ return;
18
+ if (callee.computed)
19
+ return;
20
+ if (callee.property.type !== "Identifier")
21
+ return;
22
+ // something.replaceChild(parameter0, parameter1)
23
+ if (callee.property.name === REPLACE_CHILD_NAME) {
24
+ const argument0 = call.arguments[0];
25
+ const argument1 = call.arguments[1];
26
+ if (!isIdentifierNamed(argument0, parameter0Name))
27
+ return;
28
+ if (!isIdentifierNamed(argument1, parameter1Name))
29
+ return;
30
+ found = true;
31
+ callPath.stop();
32
+ return;
33
+ }
34
+ // something.replaceChild.call(this, parameter0, parameter1)
35
+ if (callee.property.name !== "call")
36
+ return;
37
+ const target = callee.object;
38
+ if (target.type !== "MemberExpression")
39
+ return;
40
+ if (target.computed)
41
+ return;
42
+ if (target.property.type !== "Identifier")
43
+ return;
44
+ if (target.property.name !== REPLACE_CHILD_NAME)
45
+ return;
46
+ const argument1 = call.arguments[1];
47
+ const argument2 = call.arguments[2];
48
+ if (!isIdentifierNamed(argument1, parameter0Name))
49
+ return;
50
+ if (!isIdentifierNamed(argument2, parameter1Name))
51
+ return;
52
+ found = true;
53
+ callPath.stop();
54
+ },
55
+ });
56
+ return found;
57
+ };
@@ -0,0 +1 @@
1
+ export declare const isAlreadyChildParameterName: (name: string, base: string) => boolean;
@@ -0,0 +1,8 @@
1
+ export const isAlreadyChildParameterName = (name, base) => {
2
+ if (name === base)
3
+ return true;
4
+ if (!name.startsWith(base))
5
+ return false;
6
+ const suffix = name.slice(base.length);
7
+ return /^\d+$/u.test(suffix);
8
+ };
@@ -0,0 +1,2 @@
1
+ import type { ReplaceChildFunctionPath } from "./replace-child-types.js";
2
+ export declare const isReplaceChildNamedFunction: (path: ReplaceChildFunctionPath) => boolean;
@@ -0,0 +1,43 @@
1
+ import { isIdentifierNamed, isStringLiteralValue, } from "./ast-node-predicates.js";
2
+ import { REPLACE_CHILD_NAME } from "./constants.js";
3
+ const isReplaceChildKey = (key) => {
4
+ if (isIdentifierNamed(key, REPLACE_CHILD_NAME))
5
+ return true;
6
+ if (isStringLiteralValue(key, REPLACE_CHILD_NAME))
7
+ return true;
8
+ return false;
9
+ };
10
+ const isReplaceChildValueDescriptorFunction = (path) => {
11
+ const valueProperty = path.parentPath;
12
+ if (!valueProperty.isObjectProperty())
13
+ return false;
14
+ const valueKey = valueProperty.node.key;
15
+ const isValueKey = isIdentifierNamed(valueKey, "value") ||
16
+ isStringLiteralValue(valueKey, "value");
17
+ if (!isValueKey)
18
+ return false;
19
+ const descriptor = valueProperty.parentPath;
20
+ if (!descriptor.isObjectExpression())
21
+ return false;
22
+ const replaceChildProperty = descriptor.parentPath;
23
+ if (!replaceChildProperty.isObjectProperty())
24
+ return false;
25
+ return isReplaceChildKey(replaceChildProperty.node.key);
26
+ };
27
+ export const isReplaceChildNamedFunction = (path) => {
28
+ if ((path.isFunctionDeclaration() || path.isFunctionExpression()) &&
29
+ isIdentifierNamed(path.node.id, REPLACE_CHILD_NAME)) {
30
+ return true;
31
+ }
32
+ if (path.isObjectMethod() || path.isClassMethod()) {
33
+ return isReplaceChildKey(path.node.key);
34
+ }
35
+ const parent = path.parentPath;
36
+ if (parent.isObjectProperty() && isReplaceChildKey(parent.node.key)) {
37
+ return true;
38
+ }
39
+ if (path.isFunctionExpression() || path.isArrowFunctionExpression()) {
40
+ return isReplaceChildValueDescriptorFunction(path);
41
+ }
42
+ return false;
43
+ };
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameReplaceChildParametersTransform: Transform;
@@ -0,0 +1,44 @@
1
+ import { createRequire } from "node:module";
2
+ import { RenameGroup } from "../../core/stable-naming.js";
3
+ import { getFilesToProcess, } from "../../core/types.js";
4
+ import { collectReplaceChildParameterRenames } from "./collect-replace-child-parameter-renames.js";
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
+ export const renameReplaceChildParametersTransform = {
9
+ id: "rename-replace-child-parameters",
10
+ description: "Renames replaceChild forwarding wrapper parameters to $newChild and $oldChild",
11
+ scope: "file",
12
+ parallelizable: true,
13
+ transform(context) {
14
+ let nodesVisited = 0;
15
+ let transformationsApplied = 0;
16
+ for (const fileInfo of getFilesToProcess(context)) {
17
+ const group = new RenameGroup();
18
+ traverse(fileInfo.ast, {
19
+ FunctionDeclaration(path) {
20
+ nodesVisited++;
21
+ collectReplaceChildParameterRenames(path, group);
22
+ },
23
+ FunctionExpression(path) {
24
+ nodesVisited++;
25
+ collectReplaceChildParameterRenames(path, group);
26
+ },
27
+ ArrowFunctionExpression(path) {
28
+ nodesVisited++;
29
+ collectReplaceChildParameterRenames(path, group);
30
+ },
31
+ ObjectMethod(path) {
32
+ nodesVisited++;
33
+ collectReplaceChildParameterRenames(path, group);
34
+ },
35
+ ClassMethod(path) {
36
+ nodesVisited++;
37
+ collectReplaceChildParameterRenames(path, group);
38
+ },
39
+ });
40
+ transformationsApplied += group.apply();
41
+ }
42
+ return Promise.resolve({ nodesVisited, transformationsApplied });
43
+ },
44
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { ArrowFunctionExpression, ClassMethod, FunctionDeclaration, FunctionExpression, ObjectMethod } from "@babel/types";
3
+ export type ReplaceChildFunctionPath = NodePath<FunctionDeclaration> | NodePath<FunctionExpression> | NodePath<ArrowFunctionExpression> | NodePath<ObjectMethod> | NodePath<ClassMethod>;
@@ -9,6 +9,7 @@ import { renameLoopIndexVariablesTransform } from "./rename-loop-index-variables
9
9
  import { renameLoopIndexVariablesV2Transform } from "./rename-loop-index-variables-v2/rename-loop-index-variables-v2-transform.js";
10
10
  import { renameLoopIndexVariablesV3Transform } from "./rename-loop-index-variables-v3/rename-loop-index-variables-v3-transform.js";
11
11
  import { renamePromiseExecutorParametersTransform } from "./rename-promise-executor-parameters/rename-promise-executor-parameters-transform.js";
12
+ import { renameReplaceChildParametersTransform } from "./rename-replace-child-parameters/rename-replace-child-parameters-transform.js";
12
13
  import { renameTimeoutIdsTransform } from "./rename-timeout-ids/rename-timeout-ids-transform.js";
13
14
  import { renameUseReferenceGuardsTransform } from "./rename-use-reference-guards/rename-use-reference-guards-transform.js";
14
15
  import { renameUseReferenceGuardsV2Transform } from "./rename-use-reference-guards-v2/rename-use-reference-guards-v2-transform.js";
@@ -25,6 +26,7 @@ export const transformRegistry = {
25
26
  [renameLoopIndexVariablesV2Transform.id]: renameLoopIndexVariablesV2Transform,
26
27
  [renameLoopIndexVariablesV3Transform.id]: renameLoopIndexVariablesV3Transform,
27
28
  [renamePromiseExecutorParametersTransform.id]: renamePromiseExecutorParametersTransform,
29
+ [renameReplaceChildParametersTransform.id]: renameReplaceChildParametersTransform,
28
30
  [renameTimeoutIdsTransform.id]: renameTimeoutIdsTransform,
29
31
  [renameUseReferenceGuardsTransform.id]: renameUseReferenceGuardsTransform,
30
32
  [renameUseReferenceGuardsV2Transform.id]: renameUseReferenceGuardsV2Transform,
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.9.0",
5
+ "version": "1.10.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",
@@ -141,6 +141,16 @@
141
141
  "evaluatedAt": "2026-01-22T21:39:53.578Z",
142
142
  "notes": "Auto-added by evaluation script."
143
143
  },
144
+ {
145
+ "id": "rename-replace-child-parameters",
146
+ "description": "Renames replaceChild forwarding wrapper parameters to $newChild and $oldChild",
147
+ "scope": "file",
148
+ "parallelizable": true,
149
+ "diffReductionImpact": 0,
150
+ "recommended": false,
151
+ "evaluatedAt": "2026-01-23T17:28:09.184Z",
152
+ "notes": "Measured with baseline none: 0.00%."
153
+ },
144
154
  {
145
155
  "id": "expand-special-number-literals",
146
156
  "description": "Expands 1/0 to Infinity, -1/0 (and 1/-0) to -Infinity, and 0/0 to NaN (when not shadowed)",