miniread 1.27.0 → 1.28.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.
@@ -38,6 +38,12 @@ const manifestData = {
38
38
  evaluatedAt: "2026-01-23T18:15:00.000Z",
39
39
  notes: "Added manually; improves readability by reducing nesting.",
40
40
  },
41
+ "rename-awaiter-parameters": {
42
+ diffReductionImpact: 0,
43
+ recommended: true,
44
+ evaluatedAt: "2026-01-24T12:40:34.000Z",
45
+ notes: "Measured with baseline none: 0.00%. Added to recommended for readability.",
46
+ },
41
47
  "rename-catch-parameters": {
42
48
  diffReductionImpact: 0.0007738623280043599,
43
49
  recommended: true,
@@ -6,6 +6,7 @@ import { expandSequenceExpressionsV5Transform } from "../expand-sequence-express
6
6
  import { expandSpecialNumberLiteralsTransform } from "../expand-special-number-literals/expand-special-number-literals-transform.js";
7
7
  import { expandUndefinedLiteralsTransform } from "../expand-undefined-literals/expand-undefined-literals-transform.js";
8
8
  import { removeRedundantElseTransform } from "../remove-redundant-else/remove-redundant-else-transform.js";
9
+ import { renameAwaiterParametersTransform } from "../rename-awaiter-parameters/rename-awaiter-parameters-transform.js";
9
10
  import { renameCatchParametersTransform } from "../rename-catch-parameters/rename-catch-parameters-transform.js";
10
11
  import { renameCharCodeAtTransform } from "../rename-char-code-at/rename-char-code-at-transform.js";
11
12
  import { renameCharcodeVariablesTransform } from "../rename-charcode-variables/rename-charcode-variables-transform.js";
@@ -40,6 +41,7 @@ export const transformRegistry = {
40
41
  [expandSpecialNumberLiteralsTransform.id]: expandSpecialNumberLiteralsTransform,
41
42
  [expandUndefinedLiteralsTransform.id]: expandUndefinedLiteralsTransform,
42
43
  [removeRedundantElseTransform.id]: removeRedundantElseTransform,
44
+ [renameAwaiterParametersTransform.id]: renameAwaiterParametersTransform,
43
45
  [renameCatchParametersTransform.id]: renameCatchParametersTransform,
44
46
  [renameCharCodeAtTransform.id]: renameCharCodeAtTransform,
45
47
  [renameCharcodeVariablesTransform.id]: renameCharcodeVariablesTransform,
@@ -0,0 +1,12 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { Function as BabelFunction, Identifier } from "@babel/types";
3
+ type AwaiterParameterNames = {
4
+ thisArg: string;
5
+ args: string;
6
+ promiseCtor: string;
7
+ generator: string;
8
+ };
9
+ declare const isIdentifierParameters: (parameters: BabelFunction["params"]) => parameters is [Identifier, Identifier, Identifier, Identifier];
10
+ declare const hasAwaiterPattern: (path: NodePath<BabelFunction>, names: AwaiterParameterNames) => boolean;
11
+ export { hasAwaiterPattern, isIdentifierParameters };
12
+ export type { AwaiterParameterNames };
@@ -0,0 +1,101 @@
1
+ import { isIdentifier } from "@babel/types";
2
+ const isIdentifierParameters = (parameters) => {
3
+ if (parameters.length !== 4)
4
+ return false;
5
+ return parameters.every((parameter) => parameter.type === "Identifier");
6
+ };
7
+ const isIdentifierNamed = (node, name) => isIdentifier(node) && node.name === name;
8
+ const isEmptyArrayExpression = (node) => node.elements.length === 0;
9
+ const isArgumentsFallback = (node, argumentsName) => node.operator === "||" &&
10
+ isIdentifierNamed(node.left, argumentsName) &&
11
+ node.right.type === "ArrayExpression" &&
12
+ isEmptyArrayExpression(node.right);
13
+ const isGeneratorApplyCall = (node, generatorName, thisArgumentName, argumentsName) => {
14
+ const callee = node.callee;
15
+ if (callee.type !== "MemberExpression")
16
+ return false;
17
+ if (callee.computed)
18
+ return false;
19
+ if (!isIdentifierNamed(callee.object, generatorName))
20
+ return false;
21
+ if (!isIdentifierNamed(callee.property, "apply"))
22
+ return false;
23
+ if (node.arguments.length !== 2)
24
+ return false;
25
+ const [thisArgument, argumentsValue] = node.arguments;
26
+ if (!thisArgument || !argumentsValue)
27
+ return false;
28
+ if (!isIdentifierNamed(thisArgument, thisArgumentName))
29
+ return false;
30
+ if (argumentsValue.type === "Identifier") {
31
+ return argumentsValue.name === argumentsName;
32
+ }
33
+ if (argumentsValue.type !== "LogicalExpression")
34
+ return false;
35
+ return isArgumentsFallback(argumentsValue, argumentsName);
36
+ };
37
+ const isGeneratorMethodCall = (node, generatorName, methodName) => {
38
+ const callee = node.callee;
39
+ if (callee.type !== "MemberExpression")
40
+ return false;
41
+ if (callee.computed)
42
+ return false;
43
+ if (!isIdentifierNamed(callee.object, generatorName))
44
+ return false;
45
+ return isIdentifierNamed(callee.property, methodName);
46
+ };
47
+ const isPromiseCtorNewExpression = (node, promiseCtorName) => {
48
+ const callee = node.callee;
49
+ if (callee.type === "Identifier") {
50
+ return callee.name === promiseCtorName;
51
+ }
52
+ if (callee.type !== "LogicalExpression")
53
+ return false;
54
+ if (callee.operator !== "||")
55
+ return false;
56
+ if (!isIdentifierNamed(callee.left, promiseCtorName))
57
+ return false;
58
+ const right = callee.right;
59
+ if (right.type !== "AssignmentExpression")
60
+ return false;
61
+ if (right.operator !== "=")
62
+ return false;
63
+ if (!isIdentifierNamed(right.left, promiseCtorName))
64
+ return false;
65
+ return isIdentifierNamed(right.right, "Promise");
66
+ };
67
+ const isPromiseCtorInstanceof = (node, promiseCtorName) => node.operator === "instanceof" &&
68
+ isIdentifierNamed(node.right, promiseCtorName);
69
+ const hasAwaiterPattern = (path, names) => {
70
+ let hasApplyCall = false;
71
+ let hasNextCall = false;
72
+ let hasThrowCall = false;
73
+ let hasPromiseCtorUsage = false;
74
+ path.traverse({
75
+ CallExpression(innerPath) {
76
+ const node = innerPath.node;
77
+ if (isGeneratorApplyCall(node, names.generator, names.thisArg, names.args)) {
78
+ hasApplyCall = true;
79
+ }
80
+ if (isGeneratorMethodCall(node, names.generator, "next")) {
81
+ hasNextCall = true;
82
+ }
83
+ if (isGeneratorMethodCall(node, names.generator, "throw")) {
84
+ hasThrowCall = true;
85
+ }
86
+ },
87
+ NewExpression(innerPath) {
88
+ if (isPromiseCtorNewExpression(innerPath.node, names.promiseCtor)) {
89
+ hasPromiseCtorUsage = true;
90
+ }
91
+ },
92
+ BinaryExpression(innerPath) {
93
+ if (isPromiseCtorInstanceof(innerPath.node, names.promiseCtor)) {
94
+ hasPromiseCtorUsage = true;
95
+ }
96
+ },
97
+ });
98
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
99
+ return hasApplyCall && hasNextCall && hasThrowCall && hasPromiseCtorUsage;
100
+ };
101
+ export { hasAwaiterPattern, isIdentifierParameters };
@@ -0,0 +1,6 @@
1
+ {
2
+ "diffReductionImpact": 0,
3
+ "recommended": true,
4
+ "evaluatedAt": "2026-01-24T12:40:34.000Z",
5
+ "notes": "Measured with baseline none: 0.00%. Added to recommended for readability."
6
+ }
@@ -0,0 +1,5 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { Function as BabelFunction } from "@babel/types";
3
+ import type { AwaiterParameterNames } from "./awaiter-pattern.js";
4
+ declare const renameAwaiterParameters: (path: NodePath<BabelFunction>, names: AwaiterParameterNames) => number;
5
+ export { renameAwaiterParameters };
@@ -0,0 +1,49 @@
1
+ import { RenameGroup } from "../../core/stable-naming.js";
2
+ const PARAM_BASE_NAMES = {
3
+ thisArg: "thisArg",
4
+ args: "args",
5
+ promiseCtor: "promiseCtor",
6
+ generator: "generator",
7
+ };
8
+ const renameAwaiterParameters = (path, names) => {
9
+ const thisArgumentBinding = path.scope.getBinding(names.thisArg);
10
+ const argumentsBinding = path.scope.getBinding(names.args);
11
+ const promiseCtorBinding = path.scope.getBinding(names.promiseCtor);
12
+ const generatorBinding = path.scope.getBinding(names.generator);
13
+ if (!thisArgumentBinding ||
14
+ !argumentsBinding ||
15
+ !promiseCtorBinding ||
16
+ !generatorBinding) {
17
+ return 0;
18
+ }
19
+ const isOwnedByFunctionScope = (binding) => binding.scope === path.scope;
20
+ if (!isOwnedByFunctionScope(thisArgumentBinding) ||
21
+ !isOwnedByFunctionScope(argumentsBinding) ||
22
+ !isOwnedByFunctionScope(promiseCtorBinding) ||
23
+ !isOwnedByFunctionScope(generatorBinding)) {
24
+ return 0;
25
+ }
26
+ const group = new RenameGroup();
27
+ group.add({
28
+ scope: path.scope,
29
+ currentName: names.thisArg,
30
+ baseName: PARAM_BASE_NAMES.thisArg,
31
+ });
32
+ group.add({
33
+ scope: path.scope,
34
+ currentName: names.args,
35
+ baseName: PARAM_BASE_NAMES.args,
36
+ });
37
+ group.add({
38
+ scope: path.scope,
39
+ currentName: names.promiseCtor,
40
+ baseName: PARAM_BASE_NAMES.promiseCtor,
41
+ });
42
+ group.add({
43
+ scope: path.scope,
44
+ currentName: names.generator,
45
+ baseName: PARAM_BASE_NAMES.generator,
46
+ });
47
+ return group.apply();
48
+ };
49
+ export { renameAwaiterParameters };
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameAwaiterParametersTransform: Transform;
@@ -0,0 +1,48 @@
1
+ import { createRequire } from "node:module";
2
+ import { isStableRenamed } from "../../core/stable-naming.js";
3
+ import { getFilesToProcess, } from "../../core/types.js";
4
+ import { hasAwaiterPattern, isIdentifierParameters, } from "./awaiter-pattern.js";
5
+ import { renameAwaiterParameters } from "./rename-awaiter-bindings.js";
6
+ const require = createRequire(import.meta.url);
7
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
8
+ const traverse = require("@babel/traverse").default;
9
+ export const renameAwaiterParametersTransform = {
10
+ id: "rename-awaiter-parameters",
11
+ description: "Renames TypeScript __awaiter helper parameters to $thisArg/$args/$promiseCtor/$generator",
12
+ scope: "file",
13
+ parallelizable: true,
14
+ transform(context) {
15
+ let nodesVisited = 0;
16
+ let transformationsApplied = 0;
17
+ for (const fileInfo of getFilesToProcess(context)) {
18
+ traverse(fileInfo.ast, {
19
+ Function(path) {
20
+ nodesVisited++;
21
+ const parameters = path.node.params;
22
+ if (!isIdentifierParameters(parameters))
23
+ return;
24
+ const [thisArgument, argumentsValue, promiseCtor, generator] = parameters;
25
+ const names = {
26
+ thisArg: thisArgument.name,
27
+ args: argumentsValue.name,
28
+ promiseCtor: promiseCtor.name,
29
+ generator: generator.name,
30
+ };
31
+ if (isStableRenamed(names.thisArg) ||
32
+ isStableRenamed(names.args) ||
33
+ isStableRenamed(names.promiseCtor) ||
34
+ isStableRenamed(names.generator)) {
35
+ return;
36
+ }
37
+ if (!hasAwaiterPattern(path, names))
38
+ return;
39
+ transformationsApplied += renameAwaiterParameters(path, names);
40
+ },
41
+ });
42
+ }
43
+ return Promise.resolve({
44
+ nodesVisited,
45
+ transformationsApplied,
46
+ });
47
+ },
48
+ };
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.27.0",
5
+ "version": "1.28.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",