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.
- package/dist/cli/execute-transforms.d.ts +9 -0
- package/dist/cli/execute-transforms.js +39 -0
- package/dist/cli/run-transforms.js +17 -27
- package/dist/core/types.d.ts +6 -0
- package/dist/core/types.js +11 -1
- package/dist/scripts/evaluate/run-evaluations.js +7 -2
- package/dist/transforms/expand-boolean-literals/expand-boolean-literals-transform.d.ts +1 -1
- package/dist/transforms/expand-boolean-literals/expand-boolean-literals-transform.js +2 -2
- package/dist/transforms/expand-return-sequence/expand-return-sequence-transform.d.ts +1 -1
- package/dist/transforms/expand-return-sequence/expand-return-sequence-transform.js +2 -2
- package/dist/transforms/expand-sequence-expressions/expand-sequence-expressions-transform.d.ts +1 -1
- package/dist/transforms/expand-sequence-expressions/expand-sequence-expressions-transform.js +2 -2
- package/dist/transforms/expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.d.ts +1 -1
- package/dist/transforms/expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.js +2 -2
- package/dist/transforms/expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.d.ts +1 -1
- package/dist/transforms/expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.js +2 -2
- package/dist/transforms/expand-special-number-literals/expand-special-number-literals-transform.d.ts +2 -0
- package/dist/transforms/expand-special-number-literals/expand-special-number-literals-transform.js +139 -0
- package/dist/transforms/expand-throw-sequence/expand-throw-sequence-transform.d.ts +1 -1
- package/dist/transforms/expand-throw-sequence/expand-throw-sequence-transform.js +2 -2
- package/dist/transforms/expand-undefined-literals/expand-undefined-literals-transform.d.ts +1 -1
- package/dist/transforms/expand-undefined-literals/expand-undefined-literals-transform.js +2 -2
- package/dist/transforms/rename-catch-parameters/rename-catch-parameters-transform.d.ts +1 -1
- package/dist/transforms/rename-catch-parameters/rename-catch-parameters-transform.js +2 -2
- package/dist/transforms/rename-destructured-aliases/rename-destructured-aliases-transform.d.ts +1 -1
- package/dist/transforms/rename-destructured-aliases/rename-destructured-aliases-transform.js +2 -2
- package/dist/transforms/rename-loop-index-variables/rename-loop-index-variables-transform.d.ts +1 -1
- package/dist/transforms/rename-loop-index-variables/rename-loop-index-variables-transform.js +2 -2
- package/dist/transforms/rename-promise-executor-parameters/rename-promise-executor-parameters-transform.d.ts +1 -1
- package/dist/transforms/rename-promise-executor-parameters/rename-promise-executor-parameters-transform.js +2 -2
- package/dist/transforms/rename-timeout-ids/rename-timeout-ids-transform.js +2 -2
- package/dist/transforms/rename-use-reference-guards/rename-use-reference-guards-transform.d.ts +1 -1
- package/dist/transforms/rename-use-reference-guards/rename-use-reference-guards-transform.js +2 -2
- package/dist/transforms/split-variable-declarations/split-variable-declarations-transform.d.ts +1 -1
- package/dist/transforms/split-variable-declarations/split-variable-declarations-transform.js +2 -2
- package/dist/transforms/transform-registry.js +2 -0
- package/package.json +1 -1
- 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
|
-
|
|
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
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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) {
|
package/dist/core/types.d.ts
CHANGED
|
@@ -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[];
|
package/dist/core/types.js
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
57
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
58
58
|
traverse(fileInfo.ast, {
|
|
59
59
|
ReturnStatement(path) {
|
|
60
60
|
nodesVisited++;
|
package/dist/transforms/expand-sequence-expressions/expand-sequence-expressions-transform.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Transform } from "../../core/types.js";
|
|
2
2
|
export declare const expandSequenceExpressionsTransform: Transform;
|
package/dist/transforms/expand-sequence-expressions/expand-sequence-expressions-transform.js
CHANGED
|
@@ -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
|
|
16
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
17
17
|
traverse(fileInfo.ast, {
|
|
18
18
|
ExpressionStatement(path) {
|
|
19
19
|
nodesVisited++;
|
package/dist/transforms/expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Transform } from "../../core/types.js";
|
|
2
2
|
export declare const expandSequenceExpressionsV2Transform: Transform;
|
package/dist/transforms/expand-sequence-expressions-v2/expand-sequence-expressions-v2-transform.js
CHANGED
|
@@ -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
|
|
17
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
18
18
|
traverse(fileInfo.ast, {
|
|
19
19
|
ReturnStatement(path) {
|
|
20
20
|
nodesVisited++;
|
package/dist/transforms/expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Transform } from "../../core/types.js";
|
|
2
2
|
export declare const expandSequenceExpressionsV3Transform: Transform;
|
package/dist/transforms/expand-sequence-expressions-v3/expand-sequence-expressions-v3-transform.js
CHANGED
|
@@ -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
|
|
18
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
19
19
|
traverse(fileInfo.ast, {
|
|
20
20
|
ReturnStatement(path) {
|
|
21
21
|
nodesVisited++;
|
package/dist/transforms/expand-special-number-literals/expand-special-number-literals-transform.js
ADDED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
42
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
43
43
|
const renamedCatches = new WeakMap();
|
|
44
44
|
traverse(fileInfo.ast, {
|
|
45
45
|
CatchClause(path) {
|
package/dist/transforms/rename-destructured-aliases/rename-destructured-aliases-transform.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Transform } from "../../core/types.js";
|
|
2
2
|
export declare const renameDestructuredAliasesTransform: Transform;
|
package/dist/transforms/rename-destructured-aliases/rename-destructured-aliases-transform.js
CHANGED
|
@@ -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
|
|
105
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
106
106
|
traverse(fileInfo.ast, {
|
|
107
107
|
ObjectPattern(path) {
|
|
108
108
|
nodesVisited++;
|
package/dist/transforms/rename-loop-index-variables/rename-loop-index-variables-transform.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Transform } from "../../core/types.js";
|
|
2
2
|
export declare const renameLoopIndexVariablesTransform: Transform;
|
package/dist/transforms/rename-loop-index-variables/rename-loop-index-variables-transform.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
49
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
50
50
|
traverse(fileInfo.ast, {
|
|
51
51
|
VariableDeclarator(path) {
|
|
52
52
|
nodesVisited++;
|
package/dist/transforms/rename-use-reference-guards/rename-use-reference-guards-transform.js
CHANGED
|
@@ -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
|
|
17
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
18
18
|
traverse(fileInfo.ast, {
|
|
19
19
|
VariableDeclarator(path) {
|
|
20
20
|
nodesVisited++;
|
package/dist/transforms/split-variable-declarations/split-variable-declarations-transform.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Transform } from "../../core/types.js";
|
|
2
2
|
export declare const splitVariableDeclarationsTransform: Transform;
|
package/dist/transforms/split-variable-declarations/split-variable-declarations-transform.js
CHANGED
|
@@ -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
|
|
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.
|
|
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",
|
package/transform-manifest.json
CHANGED
|
@@ -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": {
|