miniread 1.92.0 → 1.93.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 (26) hide show
  1. package/dist/transforms/_generated/manifest.js +5 -0
  2. package/dist/transforms/_generated/registry.js +2 -0
  3. package/dist/transforms/recommended-transform-order.d.ts +1 -1
  4. package/dist/transforms/recommended-transform-order.js +1 -0
  5. package/dist/transforms/rename-memoized-instance-variables/manifest.json +12 -0
  6. package/dist/transforms/rename-memoized-instance-variables/rename-memoized-instance-variables-transform.d.ts +2 -0
  7. package/dist/transforms/rename-memoized-instance-variables/rename-memoized-instance-variables-transform.js +130 -0
  8. package/dist/transforms/rename-platform-win32-flags/is-safe-process-binding.js +1 -1
  9. package/dist/transforms/rename-search-parameters-variables/rename-search-parameters-variables-transform.js +2 -2
  10. package/dist/transforms/rename-url-parameters/rename-url-parameters-transform.js +1 -1
  11. package/dist/transforms/rename-url-variables/rename-url-variables-transform.js +3 -3
  12. package/dist/transforms/shared/node/is-node-require-in-scope.d.ts +2 -0
  13. package/dist/transforms/{is-require-from-url-module.js → shared/node/is-node-require-in-scope.js} +0 -80
  14. package/dist/transforms/{is-allowed-url-constructor-in-scope.js → shared/url/is-allowed-url-constructor-in-scope.js} +2 -1
  15. package/dist/transforms/{is-allowed-url-namespace-binding-in-scope.js → shared/url/is-allowed-url-namespace-binding-in-scope.js} +2 -1
  16. package/dist/transforms/{is-require-from-url-module.d.ts → shared/url/is-require-from-url-module.d.ts} +1 -3
  17. package/dist/transforms/shared/url/is-require-from-url-module.js +80 -0
  18. package/package.json +1 -1
  19. /package/dist/transforms/{get-url-construction-kind.d.ts → shared/url/get-url-construction-kind.d.ts} +0 -0
  20. /package/dist/transforms/{get-url-construction-kind.js → shared/url/get-url-construction-kind.js} +0 -0
  21. /package/dist/transforms/{is-allowed-url-constructor-in-scope.d.ts → shared/url/is-allowed-url-constructor-in-scope.d.ts} +0 -0
  22. /package/dist/transforms/{is-allowed-url-module-import-binding.d.ts → shared/url/is-allowed-url-module-import-binding.d.ts} +0 -0
  23. /package/dist/transforms/{is-allowed-url-module-import-binding.js → shared/url/is-allowed-url-module-import-binding.js} +0 -0
  24. /package/dist/transforms/{is-allowed-url-namespace-binding-in-scope.d.ts → shared/url/is-allowed-url-namespace-binding-in-scope.d.ts} +0 -0
  25. /package/dist/transforms/{url-usage-heuristics.d.ts → shared/url/url-usage-heuristics.d.ts} +0 -0
  26. /package/dist/transforms/{url-usage-heuristics.js → shared/url/url-usage-heuristics.js} +0 -0
@@ -216,6 +216,10 @@ const manifestData = {
216
216
  notes: "Measured with baseline none: 0.00%.",
217
217
  evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T20:05:17.827Z", "changedLines": 208, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 100 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T23:22:33.139Z", "changedLines": 208, "durationSeconds": 54.654894917, "stableNames": 1358 } },
218
218
  },
219
+ "rename-memoized-instance-variables": {
220
+ recommended: true,
221
+ evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 99.99246065403827, "evaluatedAt": "2026-02-06T21:01:58.503Z", "changedLines": 80, "durationSeconds": 168.58266914, "stableNames": 1359 } },
222
+ },
219
223
  "rename-object-entries-parameters": {
220
224
  recommended: true,
221
225
  evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T17:39:17.299Z", "changedLines": 248, "durationSeconds": 215.530500649, "stableNames": 1358 } },
@@ -512,6 +516,7 @@ export const recommendedTransformIds = [
512
516
  "rename-char-code-at",
513
517
  "rename-charcode-variables-v2",
514
518
  "rename-client-aliases",
519
+ "rename-memoized-instance-variables",
515
520
  "rename-comparison-flags",
516
521
  "rename-platform-win32-flags",
517
522
  "rename-date-now-start-times",
@@ -44,6 +44,7 @@ import { renameLoopIndexVariablesTransform } from "../rename-loop-index-variable
44
44
  import { renameLoopIndexVariablesV2Transform } from "../rename-loop-index-variables-v2/rename-loop-index-variables-v2-transform.js";
45
45
  import { renameLoopIndexVariablesV3Transform } from "../rename-loop-index-variables-v3/rename-loop-index-variables-v3-transform.js";
46
46
  import { renameLoopLengthVariablesTransform } from "../rename-loop-length-variables/rename-loop-length-variables-transform.js";
47
+ import { renameMemoizedInstanceVariablesTransform } from "../rename-memoized-instance-variables/rename-memoized-instance-variables-transform.js";
47
48
  import { renameObjectEntriesParametersTransform } from "../rename-object-entries-parameters/rename-object-entries-parameters-transform.js";
48
49
  import { renameObjectKeysIteratorVariablesTransform } from "../rename-object-keys-iterator-variables/rename-object-keys-iterator-variables-transform.js";
49
50
  import { renameObjectKeysReducerParametersTransform } from "../rename-object-keys-reducer-parameters/rename-object-keys-reducer-parameters-transform.js";
@@ -143,6 +144,7 @@ export const transformRegistry = {
143
144
  [renameLoopIndexVariablesV2Transform.id]: renameLoopIndexVariablesV2Transform,
144
145
  [renameLoopIndexVariablesV3Transform.id]: renameLoopIndexVariablesV3Transform,
145
146
  [renameLoopLengthVariablesTransform.id]: renameLoopLengthVariablesTransform,
147
+ [renameMemoizedInstanceVariablesTransform.id]: renameMemoizedInstanceVariablesTransform,
146
148
  [renameObjectEntriesParametersTransform.id]: renameObjectEntriesParametersTransform,
147
149
  [renameObjectKeysIteratorVariablesTransform.id]: renameObjectKeysIteratorVariablesTransform,
148
150
  [renameObjectKeysReducerParametersTransform.id]: renameObjectKeysReducerParametersTransform,
@@ -6,4 +6,4 @@
6
6
  * `recommended` prioritizes readability and includes documented heuristics
7
7
  * where edge-case behavioral differences are possible.
8
8
  */
9
- export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-default-options-parameters-v3", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-queue-traversal-variables", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-object-entries-parameters", "rename-parameters-to-match-properties-v3", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-exec-results", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-setstate-updater-parameters", "rename-file-extension-variables", "rename-string-split-variables-v2", "rename-queue-entry-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-filter-boolean-coercion", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
9
+ export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-memoized-instance-variables", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-default-options-parameters-v3", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-queue-traversal-variables", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-object-entries-parameters", "rename-parameters-to-match-properties-v3", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-exec-results", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-setstate-updater-parameters", "rename-file-extension-variables", "rename-string-split-variables-v2", "rename-queue-entry-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-filter-boolean-coercion", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
@@ -37,6 +37,7 @@ export const recommendedTransformOrder = [
37
37
  "rename-char-code-at",
38
38
  "rename-charcode-variables-v2",
39
39
  "rename-client-aliases",
40
+ "rename-memoized-instance-variables",
40
41
  "rename-comparison-flags",
41
42
  "rename-platform-win32-flags",
42
43
  "rename-date-now-start-times",
@@ -0,0 +1,12 @@
1
+ {
2
+ "recommended": true,
3
+ "evaluations": {
4
+ "claude-code-2.1.10:claude-code-2.1.11": {
5
+ "diffSizePercent": 99.99246065403827,
6
+ "evaluatedAt": "2026-02-06T21:01:58.503Z",
7
+ "changedLines": 80,
8
+ "durationSeconds": 168.58266914,
9
+ "stableNames": 1359
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameMemoizedInstanceVariablesTransform: Transform;
@@ -0,0 +1,130 @@
1
+ import { createRequire } from "node:module";
2
+ import { collectExportedNames } from "../../core/collect-exported-names.js";
3
+ import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
4
+ import { getFilesToProcess, } from "../../core/types.js";
5
+ import { hasDynamicNameLookup } from "../has-dynamic-name-lookup.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
+ const BASE_NAME = "memoizedInstance";
10
+ const isNegatedIdentifierTest = (test, name) => {
11
+ if (test.type !== "UnaryExpression")
12
+ return false;
13
+ if (test.operator !== "!")
14
+ return false;
15
+ if (test.argument.type !== "Identifier")
16
+ return false;
17
+ return test.argument.name === name;
18
+ };
19
+ const isCallbackFunctionPath = (path) => {
20
+ const parentPath = path.parentPath;
21
+ if (!parentPath)
22
+ return false;
23
+ if (!parentPath.isCallExpression() &&
24
+ !parentPath.isOptionalCallExpression() &&
25
+ !parentPath.isNewExpression())
26
+ return false;
27
+ const parentArguments = parentPath.node.arguments;
28
+ const callbackNode = path.node;
29
+ return parentArguments.includes(callbackNode);
30
+ };
31
+ const isMemoizedNewAssignment = (violationPath, name) => {
32
+ if (!violationPath.isAssignmentExpression())
33
+ return false;
34
+ const assignment = violationPath.node;
35
+ if (assignment.operator !== "=")
36
+ return false;
37
+ if (assignment.left.type !== "Identifier")
38
+ return false;
39
+ if (assignment.left.name !== name)
40
+ return false;
41
+ if (assignment.right.type !== "NewExpression")
42
+ return false;
43
+ const assignmentFunctionParent = violationPath.scope.getFunctionParent();
44
+ if (assignmentFunctionParent &&
45
+ isCallbackFunctionPath(assignmentFunctionParent.path))
46
+ return false;
47
+ const ifPath = violationPath.findParent((parent) => parent.isIfStatement() &&
48
+ parent.scope.getFunctionParent() === assignmentFunctionParent);
49
+ if (!ifPath?.isIfStatement())
50
+ return false;
51
+ const test = ifPath.node.test;
52
+ if (!isNegatedIdentifierTest(test, name))
53
+ return false;
54
+ if (ifPath.node.alternate)
55
+ return false;
56
+ const assignmentExpressionStatementPath = violationPath.parentPath;
57
+ if (!assignmentExpressionStatementPath.isExpressionStatement())
58
+ return false;
59
+ const consequentPath = ifPath.get("consequent");
60
+ if (consequentPath.isBlockStatement()) {
61
+ if (assignmentExpressionStatementPath.parentPath.node !== consequentPath.node)
62
+ return false;
63
+ if (consequentPath.node.body.length !== 1)
64
+ return false;
65
+ const [onlyConsequentStatement] = consequentPath.node.body;
66
+ if (onlyConsequentStatement !== assignmentExpressionStatementPath.node)
67
+ return false;
68
+ }
69
+ else if (assignmentExpressionStatementPath.node !== consequentPath.node) {
70
+ return false;
71
+ }
72
+ return true;
73
+ };
74
+ export const renameMemoizedInstanceVariablesTransform = {
75
+ id: "rename-memoized-instance-variables",
76
+ description: "Renames memoized instance bindings when every reassignment is a direct `id = new ...` consequent of `if (!id)` (without `else`) to $memoizedInstance/$memoizedInstance2/... or memoizedInstance/memoizedInstance2/... depending on per-scope stability",
77
+ scope: "file",
78
+ parallelizable: true,
79
+ transform(context) {
80
+ let nodesVisited = 0;
81
+ let transformationsApplied = 0;
82
+ for (const fileInfo of getFilesToProcess(context)) {
83
+ if (hasDynamicNameLookup(fileInfo.ast))
84
+ continue;
85
+ const isScript = fileInfo.ast.program.sourceType === "script";
86
+ const exportedNames = collectExportedNames(fileInfo.ast.program);
87
+ const group = new RenameGroup();
88
+ traverse(fileInfo.ast, {
89
+ VariableDeclarator(path) {
90
+ nodesVisited++;
91
+ const id = path.node.id;
92
+ if (id.type !== "Identifier")
93
+ return;
94
+ if (isStableRenamed(id.name))
95
+ return;
96
+ const init = path.node.init;
97
+ if (init)
98
+ return;
99
+ if (!path.parentPath.isVariableDeclaration())
100
+ return;
101
+ const kind = path.parentPath.node.kind;
102
+ if (kind !== "let" && kind !== "var")
103
+ return;
104
+ const binding = path.scope.getBinding(id.name);
105
+ if (!binding)
106
+ return;
107
+ if (isScript && binding.scope.block.type === "Program")
108
+ return;
109
+ if (binding.scope.block.type === "Program" &&
110
+ exportedNames.has(id.name)) {
111
+ return;
112
+ }
113
+ if (binding.referencePaths.length === 0)
114
+ return;
115
+ if (binding.constantViolations.length === 0)
116
+ return;
117
+ if (!binding.constantViolations.every((violationPath) => isMemoizedNewAssignment(violationPath, id.name)))
118
+ return;
119
+ group.add({
120
+ scope: path.scope,
121
+ currentName: id.name,
122
+ baseName: BASE_NAME,
123
+ });
124
+ },
125
+ });
126
+ transformationsApplied += group.apply();
127
+ }
128
+ return Promise.resolve({ nodesVisited, transformationsApplied });
129
+ },
130
+ };
@@ -1,4 +1,4 @@
1
- import { isNodeRequireInScope } from "../is-require-from-url-module.js";
1
+ import { isNodeRequireInScope } from "../shared/node/is-node-require-in-scope.js";
2
2
  const isProcessSpecifier = (value) => value === "process" ||
3
3
  value === "node:process" ||
4
4
  value === "process/browser" ||
@@ -1,8 +1,8 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
3
3
  import { getFilesToProcess, } from "../../core/types.js";
4
- import { getUrlConstructionKind } from "../get-url-construction-kind.js";
5
- import { isAllowedUrlConstructorInScope } from "../is-allowed-url-constructor-in-scope.js";
4
+ import { getUrlConstructionKind } from "../shared/url/get-url-construction-kind.js";
5
+ import { isAllowedUrlConstructorInScope } from "../shared/url/is-allowed-url-constructor-in-scope.js";
6
6
  import { isSearchParametersDestructureUsage, isSearchParametersForOfUsage, isSearchParametersPropertyAccess, isSearchParametersSpreadUsage, } from "./search-parameters-usage-heuristics.js";
7
7
  const require = createRequire(import.meta.url);
8
8
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -2,7 +2,7 @@ import { createRequire } from "node:module";
2
2
  import { isIdentifierName, isKeyword, isStrictBindReservedWord, } from "@babel/helper-validator-identifier";
3
3
  import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
4
4
  import { getFilesToProcess, } from "../../core/types.js";
5
- import { hasUrlDestructure } from "../url-usage-heuristics.js";
5
+ import { hasUrlDestructure } from "../shared/url/url-usage-heuristics.js";
6
6
  const require = createRequire(import.meta.url);
7
7
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
8
8
  const traverse = require("@babel/traverse").default;
@@ -1,9 +1,9 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
3
3
  import { getFilesToProcess, } from "../../core/types.js";
4
- import { hasUrlDestructure, urlPropertyNames, } from "../url-usage-heuristics.js";
5
- import { getUrlConstructionKind } from "../get-url-construction-kind.js";
6
- import { isAllowedUrlConstructorInScope } from "../is-allowed-url-constructor-in-scope.js";
4
+ import { hasUrlDestructure, urlPropertyNames, } from "../shared/url/url-usage-heuristics.js";
5
+ import { getUrlConstructionKind } from "../shared/url/get-url-construction-kind.js";
6
+ import { isAllowedUrlConstructorInScope } from "../shared/url/is-allowed-url-constructor-in-scope.js";
7
7
  const require = createRequire(import.meta.url);
8
8
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
9
9
  const traverse = require("@babel/traverse").default;
@@ -0,0 +1,2 @@
1
+ import type { Scope } from "@babel/traverse";
2
+ export declare const isNodeRequireInScope: (scope: Scope) => boolean;
@@ -1,83 +1,3 @@
1
- const getRequireFromUrlModuleArgument = (expression) => {
2
- if (expression.type !== "CallExpression")
3
- return;
4
- if (expression.callee.type !== "Identifier")
5
- return;
6
- if (expression.callee.name !== "require")
7
- return;
8
- if (expression.arguments.length !== 1)
9
- return;
10
- const argument = expression.arguments[0];
11
- if (!argument)
12
- return;
13
- if (argument.type === "StringLiteral") {
14
- if (argument.value === "url")
15
- return "url";
16
- if (argument.value === "node:url")
17
- return "node:url";
18
- return;
19
- }
20
- if (argument.type === "TemplateLiteral") {
21
- if (argument.expressions.length > 0)
22
- return;
23
- const quasi = argument.quasis[0];
24
- if (!quasi)
25
- return;
26
- const value = quasi.value.cooked ?? quasi.value.raw;
27
- if (value === "url")
28
- return "url";
29
- if (value === "node:url")
30
- return "node:url";
31
- return;
32
- }
33
- };
34
- /**
35
- * Returns `true` for:
36
- * - `require("url")` / `require("node:url")`
37
- * - `require("url").URL` / `require("node:url").URL` (or any other `propertyName`),
38
- * but only when the `propertyName` argument is provided
39
- *
40
- * Note: This helper only checks the shape of the AST. If `require` is locally
41
- * bound in the current scope (e.g. by a bundler), callers should additionally
42
- * verify that `require` refers to Node's `require()` (see
43
- * {@link isNodeRequireInScope}).
44
- */
45
- export const isRequireFromUrlModule = (node, propertyName) => {
46
- if (!node)
47
- return false;
48
- if (!propertyName)
49
- return Boolean(getRequireFromUrlModuleArgument(node));
50
- if (node.type !== "MemberExpression")
51
- return false;
52
- let memberPropertyName = undefined;
53
- if (node.computed) {
54
- if (node.property.type === "StringLiteral") {
55
- memberPropertyName = node.property.value;
56
- }
57
- else if (node.property.type === "TemplateLiteral" &&
58
- node.property.expressions.length === 0 &&
59
- node.property.quasis.length === 1) {
60
- const quasi = node.property.quasis[0];
61
- memberPropertyName = quasi?.value.cooked ?? quasi?.value.raw;
62
- }
63
- }
64
- else if (node.property.type === "Identifier") {
65
- memberPropertyName = node.property.name;
66
- }
67
- const hasMatchingProperty = memberPropertyName === propertyName;
68
- if (!hasMatchingProperty)
69
- return false;
70
- // We only accept a direct `require("url").X` (or `require("node:url").X`)
71
- // member expression; deeper chains like `require("url").X.Y` are not relevant
72
- // for our current usage and would fail the base `require("url")` check anyway.
73
- if (node.object.type !== "CallExpression")
74
- return false;
75
- if (node.object.callee.type !== "Identifier")
76
- return false;
77
- if (node.object.callee.name !== "require")
78
- return false;
79
- return Boolean(getRequireFromUrlModuleArgument(node.object));
80
- };
81
1
  export const isNodeRequireInScope = (scope) => {
82
2
  const requireBinding = scope.getBinding("require");
83
3
  if (!requireBinding) {
@@ -1,5 +1,6 @@
1
+ import { isNodeRequireInScope } from "../node/is-node-require-in-scope.js";
1
2
  import { isAllowedUrlModuleImportBinding } from "./is-allowed-url-module-import-binding.js";
2
- import { isNodeRequireInScope, isRequireFromUrlModule, } from "./is-require-from-url-module.js";
3
+ import { isRequireFromUrlModule } from "./is-require-from-url-module.js";
3
4
  const doesObjectPatternBindConstructorName = (pattern, constructorName) => {
4
5
  for (const property of pattern.properties) {
5
6
  if (property.type !== "ObjectProperty")
@@ -1,4 +1,5 @@
1
- import { isNodeRequireInScope, isRequireFromUrlModule, } from "./is-require-from-url-module.js";
1
+ import { isNodeRequireInScope } from "../node/is-node-require-in-scope.js";
2
+ import { isRequireFromUrlModule } from "./is-require-from-url-module.js";
2
3
  export const isAllowedUrlNamespaceBindingInScope = (scope, bindingName) => {
3
4
  const binding = scope.getBinding(bindingName);
4
5
  if (!binding)
@@ -1,4 +1,3 @@
1
- import type { Scope } from "@babel/traverse";
2
1
  import type { Expression } from "@babel/types";
3
2
  /**
4
3
  * Returns `true` for:
@@ -9,7 +8,6 @@ import type { Expression } from "@babel/types";
9
8
  * Note: This helper only checks the shape of the AST. If `require` is locally
10
9
  * bound in the current scope (e.g. by a bundler), callers should additionally
11
10
  * verify that `require` refers to Node's `require()` (see
12
- * {@link isNodeRequireInScope}).
11
+ * `isNodeRequireInScope`).
13
12
  */
14
13
  export declare const isRequireFromUrlModule: (node: Expression | null | undefined, propertyName?: string) => boolean;
15
- export declare const isNodeRequireInScope: (scope: Scope) => boolean;
@@ -0,0 +1,80 @@
1
+ const getRequireFromUrlModuleArgument = (expression) => {
2
+ if (expression.type !== "CallExpression")
3
+ return;
4
+ if (expression.callee.type !== "Identifier")
5
+ return;
6
+ if (expression.callee.name !== "require")
7
+ return;
8
+ if (expression.arguments.length !== 1)
9
+ return;
10
+ const argument = expression.arguments[0];
11
+ if (!argument)
12
+ return;
13
+ if (argument.type === "StringLiteral") {
14
+ if (argument.value === "url")
15
+ return "url";
16
+ if (argument.value === "node:url")
17
+ return "node:url";
18
+ return;
19
+ }
20
+ if (argument.type === "TemplateLiteral") {
21
+ if (argument.expressions.length > 0)
22
+ return;
23
+ const quasi = argument.quasis[0];
24
+ if (!quasi)
25
+ return;
26
+ const value = quasi.value.cooked ?? quasi.value.raw;
27
+ if (value === "url")
28
+ return "url";
29
+ if (value === "node:url")
30
+ return "node:url";
31
+ return;
32
+ }
33
+ };
34
+ /**
35
+ * Returns `true` for:
36
+ * - `require("url")` / `require("node:url")`
37
+ * - `require("url").URL` / `require("node:url").URL` (or any other `propertyName`),
38
+ * but only when the `propertyName` argument is provided
39
+ *
40
+ * Note: This helper only checks the shape of the AST. If `require` is locally
41
+ * bound in the current scope (e.g. by a bundler), callers should additionally
42
+ * verify that `require` refers to Node's `require()` (see
43
+ * `isNodeRequireInScope`).
44
+ */
45
+ export const isRequireFromUrlModule = (node, propertyName) => {
46
+ if (!node)
47
+ return false;
48
+ if (!propertyName)
49
+ return Boolean(getRequireFromUrlModuleArgument(node));
50
+ if (node.type !== "MemberExpression")
51
+ return false;
52
+ let memberPropertyName = undefined;
53
+ if (node.computed) {
54
+ if (node.property.type === "StringLiteral") {
55
+ memberPropertyName = node.property.value;
56
+ }
57
+ else if (node.property.type === "TemplateLiteral" &&
58
+ node.property.expressions.length === 0 &&
59
+ node.property.quasis.length === 1) {
60
+ const quasi = node.property.quasis[0];
61
+ memberPropertyName = quasi?.value.cooked ?? quasi?.value.raw;
62
+ }
63
+ }
64
+ else if (node.property.type === "Identifier") {
65
+ memberPropertyName = node.property.name;
66
+ }
67
+ const hasMatchingProperty = memberPropertyName === propertyName;
68
+ if (!hasMatchingProperty)
69
+ return false;
70
+ // We only accept a direct `require("url").X` (or `require("node:url").X`)
71
+ // member expression; deeper chains like `require("url").X.Y` are not relevant
72
+ // for our current usage and would fail the base `require("url")` check anyway.
73
+ if (node.object.type !== "CallExpression")
74
+ return false;
75
+ if (node.object.callee.type !== "Identifier")
76
+ return false;
77
+ if (node.object.callee.name !== "require")
78
+ return false;
79
+ return Boolean(getRequireFromUrlModuleArgument(node.object));
80
+ };
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.92.0",
5
+ "version": "1.93.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",