miniread 1.2.0 → 1.3.1

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 (38) hide show
  1. package/dist/cli/execute-transforms.d.ts +9 -0
  2. package/dist/cli/execute-transforms.js +39 -0
  3. package/dist/cli/run-transforms.js +17 -27
  4. package/dist/core/types.d.ts +6 -0
  5. package/dist/core/types.js +11 -1
  6. package/dist/scripts/evaluate/run-evaluations.js +7 -2
  7. package/dist/transforms/expand-boolean-literals/expand-boolean-literals-transform.d.ts +1 -1
  8. package/dist/transforms/expand-boolean-literals/expand-boolean-literals-transform.js +2 -2
  9. package/dist/transforms/expand-return-sequence/expand-return-sequence-transform.d.ts +1 -1
  10. package/dist/transforms/expand-return-sequence/expand-return-sequence-transform.js +2 -2
  11. package/dist/transforms/expand-sequence-expressions/expand-sequence-expressions-transform.d.ts +1 -1
  12. package/dist/transforms/expand-sequence-expressions/expand-sequence-expressions-transform.js +2 -2
  13. package/dist/transforms/expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.d.ts +1 -1
  14. package/dist/transforms/expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.js +2 -2
  15. package/dist/transforms/expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.d.ts +1 -1
  16. package/dist/transforms/expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.js +2 -2
  17. package/dist/transforms/expand-special-number-literals/expand-special-number-literals-transform.d.ts +2 -0
  18. package/dist/transforms/expand-special-number-literals/expand-special-number-literals-transform.js +139 -0
  19. package/dist/transforms/expand-throw-sequence/expand-throw-sequence-transform.d.ts +1 -1
  20. package/dist/transforms/expand-throw-sequence/expand-throw-sequence-transform.js +2 -2
  21. package/dist/transforms/expand-undefined-literals/expand-undefined-literals-transform.d.ts +1 -1
  22. package/dist/transforms/expand-undefined-literals/expand-undefined-literals-transform.js +2 -2
  23. package/dist/transforms/rename-catch-parameters/rename-catch-parameters-transform.d.ts +1 -1
  24. package/dist/transforms/rename-catch-parameters/rename-catch-parameters-transform.js +2 -2
  25. package/dist/transforms/rename-destructured-aliases/rename-destructured-aliases-transform.d.ts +1 -1
  26. package/dist/transforms/rename-destructured-aliases/rename-destructured-aliases-transform.js +2 -2
  27. package/dist/transforms/rename-loop-index-variables/rename-loop-index-variables-transform.d.ts +1 -1
  28. package/dist/transforms/rename-loop-index-variables/rename-loop-index-variables-transform.js +2 -2
  29. package/dist/transforms/rename-promise-executor-parameters/rename-promise-executor-parameters-transform.d.ts +1 -1
  30. package/dist/transforms/rename-promise-executor-parameters/rename-promise-executor-parameters-transform.js +2 -2
  31. package/dist/transforms/rename-timeout-ids/rename-timeout-ids-transform.js +2 -2
  32. package/dist/transforms/rename-use-reference-guards/rename-use-reference-guards-transform.d.ts +1 -1
  33. package/dist/transforms/rename-use-reference-guards/rename-use-reference-guards-transform.js +2 -2
  34. package/dist/transforms/split-variable-declarations/split-variable-declarations-transform.d.ts +1 -1
  35. package/dist/transforms/split-variable-declarations/split-variable-declarations-transform.js +2 -2
  36. package/dist/transforms/transform-registry.js +2 -0
  37. package/package.json +1 -1
  38. package/transform-manifest.json +10 -0
@@ -0,0 +1,9 @@
1
+ import type PQueue from "p-queue";
2
+ import type { Transform, ProjectGraph } from "../core/types.js";
3
+ type TransformExecutionResult = {
4
+ totalTransformations: number;
5
+ error?: string;
6
+ };
7
+ type VerboseLogger = (message: string) => void;
8
+ export declare const executeTransforms: (transforms: Transform[], projectGraph: ProjectGraph, queue: PQueue, log: VerboseLogger) => Promise<TransformExecutionResult>;
9
+ export {};
@@ -0,0 +1,39 @@
1
+ export const executeTransforms = async (transforms, projectGraph, queue, log) => {
2
+ let totalTransformations = 0;
3
+ for (const transform of transforms) {
4
+ log(`Running transform: ${transform.id}`);
5
+ try {
6
+ if (transform.scope === "file" && transform.parallelizable) {
7
+ // Run transform on each file in parallel
8
+ const fileInfos = [...projectGraph.files.values()];
9
+ const statsPromises = fileInfos.map((fileInfo) => queue.add(() => transform.transform({
10
+ projectGraph,
11
+ currentFile: fileInfo,
12
+ options: {},
13
+ })));
14
+ const allStats = await Promise.all(statsPromises);
15
+ const transformApplied = allStats.reduce((sum, stats) => sum + stats.transformationsApplied, 0);
16
+ totalTransformations += transformApplied;
17
+ log(`Applied ${transformApplied} transformation(s)`);
18
+ }
19
+ else {
20
+ // Run transform on all files at once (project-scoped or non-parallelizable)
21
+ const stats = await transform.transform({
22
+ projectGraph,
23
+ currentFile: undefined,
24
+ options: {},
25
+ });
26
+ totalTransformations += stats.transformationsApplied;
27
+ log(`Applied ${stats.transformationsApplied} transformation(s)`);
28
+ }
29
+ }
30
+ catch (error) {
31
+ const message = error instanceof Error ? error.message : String(error);
32
+ return {
33
+ totalTransformations,
34
+ error: `Transform '${transform.id}' failed: ${message}`,
35
+ };
36
+ }
37
+ }
38
+ return { totalTransformations };
39
+ };
@@ -4,6 +4,7 @@ import PQueue from "p-queue";
4
4
  import { buildProjectGraph } from "../core/project-graph.js";
5
5
  import { printDryRunSummary, writeOutputFiles } from "./output.js";
6
6
  import { generateCode } from "./generate-code.js";
7
+ import { executeTransforms } from "./execute-transforms.js";
7
8
  const logVerbose = (verbose, message) => {
8
9
  if (!verbose)
9
10
  return;
@@ -75,42 +76,31 @@ export const runTransforms = async (options) => {
75
76
  if (otherFilePaths.length > 0) {
76
77
  logVerbose(verbose, `Found ${otherFilePaths.length} other file(s) to copy`);
77
78
  }
78
- // Read all files
79
+ // Read all files in parallel
79
80
  logVerbose(verbose, "Reading files...");
80
- const parsedFiles = [];
81
- for (const filePath of sourceFilePaths) {
81
+ const parsedFiles = await Promise.all(sourceFilePaths.map(async (filePath) => {
82
82
  const content = await fs.readFile(filePath, "utf8");
83
- parsedFiles.push({ path: filePath, content });
84
- }
83
+ return { path: filePath, content };
84
+ }));
85
85
  // Build project graph (includes parsing)
86
86
  logVerbose(verbose, "Parsing files with Babel...");
87
87
  const projectGraph = buildProjectGraph(parsedFiles);
88
88
  logVerbose(verbose, `Running ${transforms.length} transform(s) with ${workers} worker(s)...`);
89
89
  // Create a queue for parallel processing
90
90
  const queue = new PQueue({ concurrency: workers });
91
- // Track results
92
- let totalTransformations = 0;
93
- // Run transforms sequentially - each mutates the AST in place
94
- for (const transform of transforms) {
95
- logVerbose(verbose, `Running transform: ${transform.id}`);
96
- try {
97
- const stats = await transform.transform({
98
- projectGraph,
99
- currentFile: undefined,
100
- options: {},
101
- });
102
- totalTransformations += stats.transformationsApplied;
103
- logVerbose(verbose, `Applied ${stats.transformationsApplied} transformation(s)`);
104
- }
105
- catch (error) {
106
- const message = error instanceof Error ? error.message : String(error);
107
- return {
108
- filesProcessed: 0,
109
- totalTransformations,
110
- errors: [`Transform '${transform.id}' failed: ${message}`],
111
- };
112
- }
91
+ // Run transforms - parallelize file-scoped parallelizable transforms
92
+ const log = (message) => {
93
+ logVerbose(verbose, message);
94
+ };
95
+ const result = await executeTransforms(transforms, projectGraph, queue, log);
96
+ if (result.error) {
97
+ return {
98
+ filesProcessed: 0,
99
+ totalTransformations: result.totalTransformations,
100
+ errors: [result.error],
101
+ };
113
102
  }
103
+ const totalTransformations = result.totalTransformations;
114
104
  // Generate final code from ASTs using @babel/generator
115
105
  const finalFiles = new Map();
116
106
  for (const [filePath, fileInfo] of projectGraph.files) {
@@ -28,3 +28,9 @@ export type Transform = {
28
28
  parallelizable: boolean;
29
29
  transform: (context: TransformContext) => Promise<TransformStats>;
30
30
  };
31
+ /**
32
+ * Returns the files to process based on the context.
33
+ * If currentFile is set, returns only that file.
34
+ * Otherwise, returns all files from the project graph.
35
+ */
36
+ export declare const getFilesToProcess: (context: TransformContext) => SourceFileInfo[];
@@ -1 +1,11 @@
1
- export {};
1
+ /**
2
+ * Returns the files to process based on the context.
3
+ * If currentFile is set, returns only that file.
4
+ * Otherwise, returns all files from the project graph.
5
+ */
6
+ export const getFilesToProcess = (context) => {
7
+ if (context.currentFile) {
8
+ return [context.currentFile];
9
+ }
10
+ return [...context.projectGraph.files.values()];
11
+ };
@@ -1,4 +1,5 @@
1
1
  import path from "node:path";
2
+ import PQueue from "p-queue";
2
3
  import { evaluatePair } from "./pair-evaluator.js";
3
4
  import { sanitizeFileComponent } from "./sanitize.js";
4
5
  export const runEvaluations = async (options) => {
@@ -6,7 +7,10 @@ export const runEvaluations = async (options) => {
6
7
  const results = [];
7
8
  const errors = [];
8
9
  const outcomes = [];
9
- for (const pair of pairs) {
10
+ // Run pairs in parallel with limited concurrency
11
+ // Each pair spawns multiple subprocesses, so limit to 2 concurrent pairs
12
+ const queue = new PQueue({ concurrency: 2 });
13
+ const evaluationPromises = pairs.map((pair) => queue.add(async () => {
10
14
  const safeFrom = sanitizeFileComponent(pair.from);
11
15
  const safeTo = sanitizeFileComponent(pair.to);
12
16
  const filePrefix = `metrics-${baselineSlug}-vs-${testSlug}_${safeFrom}_${safeTo}`;
@@ -46,6 +50,7 @@ export const runEvaluations = async (options) => {
46
50
  outcomes.push({ ok: false, pair, error: message });
47
51
  console.error(`Error evaluating ${pair.from} -> ${pair.to}: ${message}`);
48
52
  }
49
- }
53
+ }));
54
+ await Promise.all(evaluationPromises);
50
55
  return { results, errors, outcomes };
51
56
  };
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandBooleanLiteralsTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  const require = createRequire(import.meta.url);
3
4
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4
5
  const traverse = require("@babel/traverse").default;
@@ -10,10 +11,9 @@ export const expandBooleanLiteralsTransform = {
10
11
  scope: "file",
11
12
  parallelizable: true,
12
13
  transform(context) {
13
- const { projectGraph } = context;
14
14
  let nodesVisited = 0;
15
15
  let transformationsApplied = 0;
16
- for (const [, fileInfo] of projectGraph.files) {
16
+ for (const fileInfo of getFilesToProcess(context)) {
17
17
  traverse(fileInfo.ast, {
18
18
  UnaryExpression(path) {
19
19
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandReturnSequenceTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  const require = createRequire(import.meta.url);
3
4
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4
5
  const traverse = require("@babel/traverse").default;
@@ -51,10 +52,9 @@ export const expandReturnSequenceTransform = {
51
52
  scope: "file",
52
53
  parallelizable: true,
53
54
  transform(context) {
54
- const { projectGraph } = context;
55
55
  let nodesVisited = 0;
56
56
  let transformationsApplied = 0;
57
- for (const [, fileInfo] of projectGraph.files) {
57
+ for (const fileInfo of getFilesToProcess(context)) {
58
58
  traverse(fileInfo.ast, {
59
59
  ReturnStatement(path) {
60
60
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandSequenceExpressionsTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  import { tryExpandExpressionStatementSequence } from "./expand-expression-statement-sequence.js";
3
4
  import { tryExpandVariableDeclarationSequenceInitializers } from "./expand-variable-declaration-sequence.js";
4
5
  const require = createRequire(import.meta.url);
@@ -10,10 +11,9 @@ export const expandSequenceExpressionsTransform = {
10
11
  scope: "file",
11
12
  parallelizable: true,
12
13
  transform(context) {
13
- const { projectGraph } = context;
14
14
  let nodesVisited = 0;
15
15
  let transformationsApplied = 0;
16
- for (const [, fileInfo] of projectGraph.files) {
16
+ for (const fileInfo of getFilesToProcess(context)) {
17
17
  traverse(fileInfo.ast, {
18
18
  ExpressionStatement(path) {
19
19
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandSequenceExpressionsV2Transform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  import { tryExpandExpressionStatementSequence } from "./expand-expression-statement-sequence.js";
3
4
  import { tryExpandReturnSequence } from "./expand-return-sequence.js";
4
5
  import { tryExpandVariableDeclarationSequenceInitializers } from "./expand-variable-declaration-sequence.js";
@@ -11,10 +12,9 @@ export const expandSequenceExpressionsV2Transform = {
11
12
  scope: "file",
12
13
  parallelizable: true,
13
14
  transform(context) {
14
- const { projectGraph } = context;
15
15
  let nodesVisited = 0;
16
16
  let transformationsApplied = 0;
17
- for (const [, fileInfo] of projectGraph.files) {
17
+ for (const fileInfo of getFilesToProcess(context)) {
18
18
  traverse(fileInfo.ast, {
19
19
  ReturnStatement(path) {
20
20
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandSequenceExpressionsV3Transform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  import { tryExpandExpressionStatementSequence } from "./expand-expression-statement-sequence.js";
3
4
  import { tryExpandReturnSequence } from "./expand-return-sequence.js";
4
5
  import { tryExpandThrowSequence } from "./expand-throw-sequence.js";
@@ -12,10 +13,9 @@ export const expandSequenceExpressionsV3Transform = {
12
13
  scope: "file",
13
14
  parallelizable: true,
14
15
  transform(context) {
15
- const { projectGraph } = context;
16
16
  let nodesVisited = 0;
17
17
  let transformationsApplied = 0;
18
- for (const [, fileInfo] of projectGraph.files) {
18
+ for (const fileInfo of getFilesToProcess(context)) {
19
19
  traverse(fileInfo.ast, {
20
20
  ReturnStatement(path) {
21
21
  nodesVisited++;
@@ -0,0 +1,2 @@
1
+ import type { Transform } from "../../core/types.js";
2
+ export declare const expandSpecialNumberLiteralsTransform: Transform;
@@ -0,0 +1,139 @@
1
+ import { createRequire } from "node:module";
2
+ import { getFilesToProcess } from "../../core/types.js";
3
+ const require = createRequire(import.meta.url);
4
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5
+ const traverse = require("@babel/traverse").default;
6
+ const t = require("@babel/types");
7
+ const directEvalCache = new WeakMap();
8
+ const containsDirectEval = (container) => {
9
+ const cached = directEvalCache.get(container.node);
10
+ if (cached !== undefined)
11
+ return cached;
12
+ let found = false;
13
+ container.traverse({
14
+ CallExpression(callPath) {
15
+ if (callPath.node.callee.type !== "Identifier")
16
+ return;
17
+ if (callPath.node.callee.name !== "eval")
18
+ return;
19
+ // We only care about direct eval in sloppy mode because it can introduce `var`
20
+ // bindings into the current function scope (which could shadow `Infinity`/`NaN`
21
+ // and change the meaning of an identifier replacement).
22
+ //
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
+ found = true;
27
+ callPath.stop();
28
+ },
29
+ Function(functionPath) {
30
+ if (functionPath.node === container.node)
31
+ return;
32
+ functionPath.skip();
33
+ },
34
+ });
35
+ directEvalCache.set(container.node, found);
36
+ return found;
37
+ };
38
+ const isWithinWithStatement = (path) => {
39
+ return Boolean(path.findParent((p) => p.isWithStatement()));
40
+ };
41
+ const isWithinSloppyDirectEvalScope = (path) => {
42
+ for (let functionPath = path.getFunctionParent(); functionPath; functionPath = functionPath.getFunctionParent()) {
43
+ if (functionPath.isInStrictMode())
44
+ continue;
45
+ if (containsDirectEval(functionPath))
46
+ return true;
47
+ }
48
+ const programPath = path.scope.getProgramParent().path;
49
+ if (!programPath.isInStrictMode() && containsDirectEval(programPath)) {
50
+ return true;
51
+ }
52
+ return false;
53
+ };
54
+ const isDivisionByZero = (value) => {
55
+ return value === 0 || Object.is(value, -0);
56
+ };
57
+ export const expandSpecialNumberLiteralsTransform = {
58
+ id: "expand-special-number-literals",
59
+ description: "Expands 1/0 to Infinity, -1/0 (and 1/-0) to -Infinity, and 0/0 to NaN (when not shadowed)",
60
+ scope: "file",
61
+ parallelizable: true,
62
+ transform(context) {
63
+ let nodesVisited = 0;
64
+ let transformationsApplied = 0;
65
+ for (const fileInfo of getFilesToProcess(context)) {
66
+ traverse(fileInfo.ast, {
67
+ BinaryExpression(path) {
68
+ nodesVisited++;
69
+ const { operator, left } = path.node;
70
+ if (operator !== "/")
71
+ return;
72
+ // Babel types allow `PrivateName` as a BinaryExpression operand for `#x in obj`
73
+ // brand checks (operator `in`). This guard is just to satisfy the type system.
74
+ if (left.type === "PrivateName")
75
+ return;
76
+ const leftPath = path.get("left");
77
+ 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
+ const rightEvaluation = rightPath.evaluate();
89
+ if (!rightEvaluation.confident)
90
+ return;
91
+ if (typeof rightEvaluation.value !== "number")
92
+ return;
93
+ const rightValue = rightEvaluation.value;
94
+ if (!isDivisionByZero(rightValue))
95
+ return;
96
+ const result = leftValue / rightValue;
97
+ if (Number.isNaN(result)) {
98
+ // `0/0` is unaffected by dynamic scope, but `NaN` can be shadowed via `with` and
99
+ // sloppy direct `eval()` in this scope or any enclosing scope.
100
+ if (isWithinWithStatement(path))
101
+ return;
102
+ if (isWithinSloppyDirectEvalScope(path))
103
+ return;
104
+ if (path.scope.hasBinding("NaN", true))
105
+ return;
106
+ path.replaceWith(t.identifier("NaN"));
107
+ transformationsApplied++;
108
+ return;
109
+ }
110
+ if (result === Infinity) {
111
+ // `1/0` is unaffected by dynamic scope, but `Infinity` can be shadowed via `with` and
112
+ // sloppy direct `eval()` in this scope or any enclosing scope.
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++;
132
+ return;
133
+ }
134
+ },
135
+ });
136
+ }
137
+ return Promise.resolve({ nodesVisited, transformationsApplied });
138
+ },
139
+ };
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandThrowSequenceTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  const require = createRequire(import.meta.url);
3
4
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4
5
  const traverse = require("@babel/traverse").default;
@@ -99,10 +100,9 @@ export const expandThrowSequenceTransform = {
99
100
  scope: "file",
100
101
  parallelizable: true,
101
102
  transform(context) {
102
- const { projectGraph } = context;
103
103
  let nodesVisited = 0;
104
104
  let transformationsApplied = 0;
105
- for (const [, fileInfo] of projectGraph.files) {
105
+ for (const fileInfo of getFilesToProcess(context)) {
106
106
  traverse(fileInfo.ast, {
107
107
  ThrowStatement(path) {
108
108
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const expandUndefinedLiteralsTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  const require = createRequire(import.meta.url);
3
4
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4
5
  const traverse = require("@babel/traverse").default;
@@ -10,10 +11,9 @@ export const expandUndefinedLiteralsTransform = {
10
11
  scope: "file",
11
12
  parallelizable: true,
12
13
  transform(context) {
13
- const { projectGraph } = context;
14
14
  let nodesVisited = 0;
15
15
  let transformationsApplied = 0;
16
- for (const [, fileInfo] of projectGraph.files) {
16
+ for (const fileInfo of getFilesToProcess(context)) {
17
17
  traverse(fileInfo.ast, {
18
18
  UnaryExpression(path) {
19
19
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const renameCatchParametersTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  const require = createRequire(import.meta.url);
3
4
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4
5
  const traverse = require("@babel/traverse").default;
@@ -36,10 +37,9 @@ export const renameCatchParametersTransform = {
36
37
  scope: "file",
37
38
  parallelizable: true,
38
39
  transform(context) {
39
- const { projectGraph } = context;
40
40
  let nodesVisited = 0;
41
41
  let transformationsApplied = 0;
42
- for (const [, fileInfo] of projectGraph.files) {
42
+ for (const fileInfo of getFilesToProcess(context)) {
43
43
  const renamedCatches = new WeakMap();
44
44
  traverse(fileInfo.ast, {
45
45
  CatchClause(path) {
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const renameDestructuredAliasesTransform: Transform;
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { isIdentifierName, isKeyword, isStrictBindReservedWord, } from "@babel/helper-validator-identifier";
3
+ import { getFilesToProcess, } from "../../core/types.js";
3
4
  import { isBindingContext } from "./binding-context.js";
4
5
  const require = createRequire(import.meta.url);
5
6
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -99,10 +100,9 @@ export const renameDestructuredAliasesTransform = {
99
100
  scope: "file",
100
101
  parallelizable: true,
101
102
  transform(context) {
102
- const { projectGraph } = context;
103
103
  let nodesVisited = 0;
104
104
  const stats = { transformationsApplied: 0 };
105
- for (const [, fileInfo] of projectGraph.files) {
105
+ for (const fileInfo of getFilesToProcess(context)) {
106
106
  traverse(fileInfo.ast, {
107
107
  ObjectPattern(path) {
108
108
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const renameLoopIndexVariablesTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  const require = createRequire(import.meta.url);
3
4
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4
5
  const traverse = require("@babel/traverse").default;
@@ -94,10 +95,9 @@ export const renameLoopIndexVariablesTransform = {
94
95
  scope: "file",
95
96
  parallelizable: true,
96
97
  transform(context) {
97
- const { projectGraph } = context;
98
98
  let nodesVisited = 0;
99
99
  let transformationsApplied = 0;
100
- for (const [, fileInfo] of projectGraph.files) {
100
+ for (const fileInfo of getFilesToProcess(context)) {
101
101
  const renamedLoops = new WeakMap();
102
102
  traverse(fileInfo.ast, {
103
103
  ForStatement(path) {
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const renamePromiseExecutorParametersTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  import { getExecutorFunctionIfEligible, isAssignedToOnHandlerProperty, isDirectCallOfBinding, wouldShadowReferencedOuterBinding, } from "./promise-executor-heuristics.js";
3
4
  import { canRenameBindingSafely, renameBindingIfSafe, } from "./rename-binding-if-safe.js";
4
5
  const require = createRequire(import.meta.url);
@@ -10,10 +11,9 @@ export const renamePromiseExecutorParametersTransform = {
10
11
  scope: "file",
11
12
  parallelizable: true,
12
13
  transform(context) {
13
- const { projectGraph } = context;
14
14
  let nodesVisited = 0;
15
15
  let transformationsApplied = 0;
16
- for (const [, fileInfo] of projectGraph.files) {
16
+ for (const fileInfo of getFilesToProcess(context)) {
17
17
  traverse(fileInfo.ast, {
18
18
  NewExpression(path) {
19
19
  nodesVisited++;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess } from "../../core/types.js";
2
3
  import { getTargetName } from "../rename-binding/get-target-name.js";
3
4
  const require = createRequire(import.meta.url);
4
5
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -43,10 +44,9 @@ export const renameTimeoutIdsTransform = {
43
44
  scope: "file",
44
45
  parallelizable: true,
45
46
  transform(context) {
46
- const { projectGraph } = context;
47
47
  let nodesVisited = 0;
48
48
  let transformationsApplied = 0;
49
- for (const [, fileInfo] of projectGraph.files) {
49
+ for (const fileInfo of getFilesToProcess(context)) {
50
50
  traverse(fileInfo.ast, {
51
51
  VariableDeclarator(path) {
52
52
  nodesVisited++;
@@ -1,3 +1,3 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  declare const renameUseReferenceGuardsTransform: Transform;
3
3
  export { renameUseReferenceGuardsTransform };
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  import { getReferenceUsage } from "./get-reference-usage.js";
3
4
  import { getTargetName } from "./get-target-name.js";
4
5
  import { isUseReferenceFalseInitializer } from "./is-use-reference-false-initializer.js";
@@ -11,10 +12,9 @@ const renameUseReferenceGuardsTransform = {
11
12
  scope: "file",
12
13
  parallelizable: true,
13
14
  transform(context) {
14
- const { projectGraph } = context;
15
15
  let nodesVisited = 0;
16
16
  let transformationsApplied = 0;
17
- for (const [, fileInfo] of projectGraph.files) {
17
+ for (const fileInfo of getFilesToProcess(context)) {
18
18
  traverse(fileInfo.ast, {
19
19
  VariableDeclarator(path) {
20
20
  nodesVisited++;
@@ -1,2 +1,2 @@
1
- import type { Transform } from "../../core/types.js";
1
+ import { type Transform } from "../../core/types.js";
2
2
  export declare const splitVariableDeclarationsTransform: Transform;
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { getFilesToProcess, } from "../../core/types.js";
2
3
  import { createVariableDeclarationFromDeclarator } from "./create-variable-declaration.js";
3
4
  import { isSafeToSplitVariableDeclaration } from "./is-safe-to-split-variable-declaration.js";
4
5
  const require = createRequire(import.meta.url);
@@ -31,10 +32,9 @@ export const splitVariableDeclarationsTransform = {
31
32
  scope: "file",
32
33
  parallelizable: true,
33
34
  transform(context) {
34
- const { projectGraph } = context;
35
35
  let nodesVisited = 0;
36
36
  let transformationsApplied = 0;
37
- for (const [, fileInfo] of projectGraph.files) {
37
+ for (const fileInfo of getFilesToProcess(context)) {
38
38
  traverse(fileInfo.ast, {
39
39
  ExportNamedDeclaration(path) {
40
40
  nodesVisited++;
@@ -2,6 +2,7 @@ import { expandBooleanLiteralsTransform } from "./expand-boolean-literals/expand
2
2
  import { expandReturnSequenceTransform } from "./expand-return-sequence/expand-return-sequence-transform.js";
3
3
  import { expandSequenceExpressionsTransform } from "./expand-sequence-expressions/expand-sequence-expressions-transform.js";
4
4
  import { expandSequenceExpressionsV2Transform } from "./expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.js";
5
+ import { expandSpecialNumberLiteralsTransform } from "./expand-special-number-literals/expand-special-number-literals-transform.js";
5
6
  import { expandSequenceExpressionsV3Transform } from "./expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.js";
6
7
  import { expandThrowSequenceTransform } from "./expand-throw-sequence/expand-throw-sequence-transform.js";
7
8
  import { expandUndefinedLiteralsTransform } from "./expand-undefined-literals/expand-undefined-literals-transform.js";
@@ -18,6 +19,7 @@ export const transformRegistry = {
18
19
  [expandSequenceExpressionsTransform.id]: expandSequenceExpressionsTransform,
19
20
  [expandSequenceExpressionsV2Transform.id]: expandSequenceExpressionsV2Transform,
20
21
  [expandSequenceExpressionsV3Transform.id]: expandSequenceExpressionsV3Transform,
22
+ [expandSpecialNumberLiteralsTransform.id]: expandSpecialNumberLiteralsTransform,
21
23
  [expandThrowSequenceTransform.id]: expandThrowSequenceTransform,
22
24
  [expandUndefinedLiteralsTransform.id]: expandUndefinedLiteralsTransform,
23
25
  [renameCatchParametersTransform.id]: renameCatchParametersTransform,
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.2.0",
5
+ "version": "1.3.1",
6
6
  "description": "Transform minified JavaScript/TypeScript into a more readable form using deterministic AST-based transforms.",
7
7
  "repository": {
8
8
  "type": "git",
@@ -139,6 +139,16 @@
139
139
  "recommended": true,
140
140
  "evaluatedAt": "2026-01-22T21:39:53.578Z",
141
141
  "notes": "Auto-added by evaluation script."
142
+ },
143
+ {
144
+ "id": "expand-special-number-literals",
145
+ "description": "Expands 1/0 to Infinity, -1/0 (and 1/-0) to -Infinity, and 0/0 to NaN (when not shadowed)",
146
+ "scope": "file",
147
+ "parallelizable": true,
148
+ "diffReductionImpact": 0,
149
+ "recommended": true,
150
+ "evaluatedAt": "2026-01-23T08:17:45.579Z",
151
+ "notes": "Auto-added by evaluation script."
142
152
  }
143
153
  ],
144
154
  "presetStats": {