miniread 1.92.0 → 1.94.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.
- package/dist/transforms/_generated/manifest.js +11 -0
- package/dist/transforms/_generated/registry.js +4 -0
- package/dist/transforms/recommended-transform-order.d.ts +1 -1
- package/dist/transforms/recommended-transform-order.js +2 -0
- package/dist/transforms/rename-dirent-parameters/get-member-property-name.d.ts +3 -0
- package/dist/transforms/rename-dirent-parameters/get-member-property-name.js +10 -0
- package/dist/transforms/rename-dirent-parameters/is-dirent-callback-parameter-binding.d.ts +2 -0
- package/dist/transforms/rename-dirent-parameters/is-dirent-callback-parameter-binding.js +111 -0
- package/dist/transforms/rename-dirent-parameters/is-dirent-method-call.d.ts +3 -0
- package/dist/transforms/rename-dirent-parameters/is-dirent-method-call.js +26 -0
- package/dist/transforms/rename-dirent-parameters/manifest.json +13 -0
- package/dist/transforms/rename-dirent-parameters/rename-dirent-parameters-transform.d.ts +2 -0
- package/dist/transforms/rename-dirent-parameters/rename-dirent-parameters-transform.js +70 -0
- package/dist/transforms/rename-memoized-instance-variables/manifest.json +12 -0
- package/dist/transforms/rename-memoized-instance-variables/rename-memoized-instance-variables-transform.d.ts +2 -0
- package/dist/transforms/rename-memoized-instance-variables/rename-memoized-instance-variables-transform.js +130 -0
- package/dist/transforms/rename-platform-win32-flags/is-safe-process-binding.js +1 -1
- package/dist/transforms/rename-search-parameters-variables/rename-search-parameters-variables-transform.js +2 -2
- package/dist/transforms/rename-url-parameters/rename-url-parameters-transform.js +1 -1
- package/dist/transforms/rename-url-variables/rename-url-variables-transform.js +3 -3
- package/dist/transforms/shared/node/is-node-require-in-scope.d.ts +2 -0
- package/dist/transforms/{is-require-from-url-module.js → shared/node/is-node-require-in-scope.js} +0 -80
- package/dist/transforms/{is-allowed-url-constructor-in-scope.js → shared/url/is-allowed-url-constructor-in-scope.js} +2 -1
- package/dist/transforms/{is-allowed-url-namespace-binding-in-scope.js → shared/url/is-allowed-url-namespace-binding-in-scope.js} +2 -1
- package/dist/transforms/{is-require-from-url-module.d.ts → shared/url/is-require-from-url-module.d.ts} +1 -3
- package/dist/transforms/shared/url/is-require-from-url-module.js +80 -0
- package/package.json +1 -1
- /package/dist/transforms/{get-url-construction-kind.d.ts → shared/url/get-url-construction-kind.d.ts} +0 -0
- /package/dist/transforms/{get-url-construction-kind.js → shared/url/get-url-construction-kind.js} +0 -0
- /package/dist/transforms/{is-allowed-url-constructor-in-scope.d.ts → shared/url/is-allowed-url-constructor-in-scope.d.ts} +0 -0
- /package/dist/transforms/{is-allowed-url-module-import-binding.d.ts → shared/url/is-allowed-url-module-import-binding.d.ts} +0 -0
- /package/dist/transforms/{is-allowed-url-module-import-binding.js → shared/url/is-allowed-url-module-import-binding.js} +0 -0
- /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
- /package/dist/transforms/{url-usage-heuristics.d.ts → shared/url/url-usage-heuristics.d.ts} +0 -0
- /package/dist/transforms/{url-usage-heuristics.js → shared/url/url-usage-heuristics.js} +0 -0
|
@@ -131,6 +131,11 @@ const manifestData = {
|
|
|
131
131
|
notes: "Auto-added by evaluation script. Measured with baseline none: 0.09%.",
|
|
132
132
|
evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T19:59:48.188Z", "changedLines": 38927, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 97.80020410477378 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 97.80020410477378, "evaluatedAt": "2026-01-25T23:15:44.243Z", "changedLines": 38927, "durationSeconds": 76.61873741599999, "stableNames": 4505 } },
|
|
133
133
|
},
|
|
134
|
+
"rename-dirent-parameters": {
|
|
135
|
+
recommended: true,
|
|
136
|
+
notes: "stableNames counts unique `$...` identifiers in transformed output for this transform run, so this value can differ across transforms.",
|
|
137
|
+
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T21:03:02.730Z", "changedLines": 518, "durationSeconds": 177.77177340999998, "stableNames": 1360 } },
|
|
138
|
+
},
|
|
134
139
|
"rename-document-fragment-variables": {
|
|
135
140
|
recommended: true,
|
|
136
141
|
evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-02T22:12:52.993Z", "changedLines": 20, "durationSeconds": 207.34089557, "stableNames": 1358 } },
|
|
@@ -216,6 +221,10 @@ const manifestData = {
|
|
|
216
221
|
notes: "Measured with baseline none: 0.00%.",
|
|
217
222
|
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
223
|
},
|
|
224
|
+
"rename-memoized-instance-variables": {
|
|
225
|
+
recommended: true,
|
|
226
|
+
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 } },
|
|
227
|
+
},
|
|
219
228
|
"rename-object-entries-parameters": {
|
|
220
229
|
recommended: true,
|
|
221
230
|
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 +521,7 @@ export const recommendedTransformIds = [
|
|
|
512
521
|
"rename-char-code-at",
|
|
513
522
|
"rename-charcode-variables-v2",
|
|
514
523
|
"rename-client-aliases",
|
|
524
|
+
"rename-memoized-instance-variables",
|
|
515
525
|
"rename-comparison-flags",
|
|
516
526
|
"rename-platform-win32-flags",
|
|
517
527
|
"rename-date-now-start-times",
|
|
@@ -531,6 +541,7 @@ export const recommendedTransformIds = [
|
|
|
531
541
|
"rename-add-event-listener-parameters",
|
|
532
542
|
"rename-http-server-parameters",
|
|
533
543
|
"rename-fs-sync-variables",
|
|
544
|
+
"rename-dirent-parameters",
|
|
534
545
|
"rename-http-method-parameters",
|
|
535
546
|
"rename-interval-ids",
|
|
536
547
|
"rename-indexeddb-request-variables",
|
|
@@ -26,6 +26,7 @@ import { renameDefaultOptionsParametersV3Transform } from "../rename-default-opt
|
|
|
26
26
|
import { renameDeferredResolveParametersTransform } from "../rename-deferred-resolve-parameters/rename-deferred-resolve-parameters-transform.js";
|
|
27
27
|
import { renameDeferredResolveParametersV2Transform } from "../rename-deferred-resolve-parameters-v2/rename-deferred-resolve-parameters-v2-transform.js";
|
|
28
28
|
import { renameDestructuredAliasesTransform } from "../rename-destructured-aliases/rename-destructured-aliases-transform.js";
|
|
29
|
+
import { renameDirentParametersTransform } from "../rename-dirent-parameters/rename-dirent-parameters-transform.js";
|
|
29
30
|
import { renameDocumentFragmentVariablesTransform } from "../rename-document-fragment-variables/rename-document-fragment-variables-transform.js";
|
|
30
31
|
import { renameErrorFirstCallbackParametersTransform } from "../rename-error-first-callback-parameters/rename-error-first-callback-parameters-transform.js";
|
|
31
32
|
import { renameErrorFirstCallbackParametersV2Transform } from "../rename-error-first-callback-parameters-v2/rename-error-first-callback-parameters-v2-transform.js";
|
|
@@ -44,6 +45,7 @@ import { renameLoopIndexVariablesTransform } from "../rename-loop-index-variable
|
|
|
44
45
|
import { renameLoopIndexVariablesV2Transform } from "../rename-loop-index-variables-v2/rename-loop-index-variables-v2-transform.js";
|
|
45
46
|
import { renameLoopIndexVariablesV3Transform } from "../rename-loop-index-variables-v3/rename-loop-index-variables-v3-transform.js";
|
|
46
47
|
import { renameLoopLengthVariablesTransform } from "../rename-loop-length-variables/rename-loop-length-variables-transform.js";
|
|
48
|
+
import { renameMemoizedInstanceVariablesTransform } from "../rename-memoized-instance-variables/rename-memoized-instance-variables-transform.js";
|
|
47
49
|
import { renameObjectEntriesParametersTransform } from "../rename-object-entries-parameters/rename-object-entries-parameters-transform.js";
|
|
48
50
|
import { renameObjectKeysIteratorVariablesTransform } from "../rename-object-keys-iterator-variables/rename-object-keys-iterator-variables-transform.js";
|
|
49
51
|
import { renameObjectKeysReducerParametersTransform } from "../rename-object-keys-reducer-parameters/rename-object-keys-reducer-parameters-transform.js";
|
|
@@ -125,6 +127,7 @@ export const transformRegistry = {
|
|
|
125
127
|
[renameDeferredResolveParametersTransform.id]: renameDeferredResolveParametersTransform,
|
|
126
128
|
[renameDeferredResolveParametersV2Transform.id]: renameDeferredResolveParametersV2Transform,
|
|
127
129
|
[renameDestructuredAliasesTransform.id]: renameDestructuredAliasesTransform,
|
|
130
|
+
[renameDirentParametersTransform.id]: renameDirentParametersTransform,
|
|
128
131
|
[renameDocumentFragmentVariablesTransform.id]: renameDocumentFragmentVariablesTransform,
|
|
129
132
|
[renameErrorFirstCallbackParametersTransform.id]: renameErrorFirstCallbackParametersTransform,
|
|
130
133
|
[renameErrorFirstCallbackParametersV2Transform.id]: renameErrorFirstCallbackParametersV2Transform,
|
|
@@ -143,6 +146,7 @@ export const transformRegistry = {
|
|
|
143
146
|
[renameLoopIndexVariablesV2Transform.id]: renameLoopIndexVariablesV2Transform,
|
|
144
147
|
[renameLoopIndexVariablesV3Transform.id]: renameLoopIndexVariablesV3Transform,
|
|
145
148
|
[renameLoopLengthVariablesTransform.id]: renameLoopLengthVariablesTransform,
|
|
149
|
+
[renameMemoizedInstanceVariablesTransform.id]: renameMemoizedInstanceVariablesTransform,
|
|
146
150
|
[renameObjectEntriesParametersTransform.id]: renameObjectEntriesParametersTransform,
|
|
147
151
|
[renameObjectKeysIteratorVariablesTransform.id]: renameObjectKeysIteratorVariablesTransform,
|
|
148
152
|
[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-dirent-parameters", "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",
|
|
@@ -59,6 +60,7 @@ export const recommendedTransformOrder = [
|
|
|
59
60
|
// are already stable-hashed. This transform gives remaining non-stable `fs` helpers stable
|
|
60
61
|
// `$fs`-style names.
|
|
61
62
|
"rename-fs-sync-variables",
|
|
63
|
+
"rename-dirent-parameters",
|
|
62
64
|
"rename-http-method-parameters",
|
|
63
65
|
"rename-interval-ids",
|
|
64
66
|
"rename-indexeddb-request-variables",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const getMemberPropertyName = (member) => {
|
|
2
|
+
if (member.computed) {
|
|
3
|
+
if (member.property.type !== "StringLiteral")
|
|
4
|
+
return;
|
|
5
|
+
return member.property.value;
|
|
6
|
+
}
|
|
7
|
+
if (member.property.type !== "Identifier")
|
|
8
|
+
return;
|
|
9
|
+
return member.property.name;
|
|
10
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { getMemberPropertyName } from "./get-member-property-name.js";
|
|
2
|
+
const iterableMethodNames = new Set([
|
|
3
|
+
"every",
|
|
4
|
+
"filter",
|
|
5
|
+
"flatMap",
|
|
6
|
+
"find",
|
|
7
|
+
"findLast",
|
|
8
|
+
"findLastIndex",
|
|
9
|
+
"findIndex",
|
|
10
|
+
"forEach",
|
|
11
|
+
"map",
|
|
12
|
+
"some",
|
|
13
|
+
]);
|
|
14
|
+
const unwrapTransparentExpressionNode = (expression) => {
|
|
15
|
+
if (expression.type === "ParenthesizedExpression") {
|
|
16
|
+
return unwrapTransparentExpressionNode(expression.expression);
|
|
17
|
+
}
|
|
18
|
+
if (expression.type === "TSAsExpression") {
|
|
19
|
+
return unwrapTransparentExpressionNode(expression.expression);
|
|
20
|
+
}
|
|
21
|
+
if (expression.type === "TSSatisfiesExpression") {
|
|
22
|
+
return unwrapTransparentExpressionNode(expression.expression);
|
|
23
|
+
}
|
|
24
|
+
if (expression.type === "TSTypeAssertion") {
|
|
25
|
+
return unwrapTransparentExpressionNode(expression.expression);
|
|
26
|
+
}
|
|
27
|
+
if (expression.type === "TSNonNullExpression") {
|
|
28
|
+
return unwrapTransparentExpressionNode(expression.expression);
|
|
29
|
+
}
|
|
30
|
+
return expression;
|
|
31
|
+
};
|
|
32
|
+
const isIterableCallbackCall = (path) => {
|
|
33
|
+
const callee = path.node.callee;
|
|
34
|
+
if ((callee.type !== "MemberExpression" &&
|
|
35
|
+
callee.type !== "OptionalMemberExpression") ||
|
|
36
|
+
!iterableMethodNames.has(getMemberPropertyName(callee) ?? "")) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const [firstArgument] = path.node.arguments;
|
|
40
|
+
if (!firstArgument)
|
|
41
|
+
return false;
|
|
42
|
+
if (firstArgument.type === "SpreadElement")
|
|
43
|
+
return false;
|
|
44
|
+
if (firstArgument.type === "ArgumentPlaceholder")
|
|
45
|
+
return false;
|
|
46
|
+
const unwrappedFirstArgument = unwrapTransparentExpressionNode(firstArgument);
|
|
47
|
+
return (unwrappedFirstArgument.type === "FunctionExpression" ||
|
|
48
|
+
unwrappedFirstArgument.type === "ArrowFunctionExpression");
|
|
49
|
+
};
|
|
50
|
+
const unwrapTransparentExpressionPath = (path) => {
|
|
51
|
+
const parentPath = path.parentPath;
|
|
52
|
+
const parentNode = parentPath.node;
|
|
53
|
+
if (parentNode.type !== "ParenthesizedExpression" &&
|
|
54
|
+
parentNode.type !== "TSAsExpression" &&
|
|
55
|
+
parentNode.type !== "TSSatisfiesExpression" &&
|
|
56
|
+
parentNode.type !== "TSTypeAssertion" &&
|
|
57
|
+
parentNode.type !== "TSNonNullExpression") {
|
|
58
|
+
return path;
|
|
59
|
+
}
|
|
60
|
+
if (parentNode.expression !== path.node)
|
|
61
|
+
return path;
|
|
62
|
+
return unwrapTransparentExpressionPath(parentPath);
|
|
63
|
+
};
|
|
64
|
+
const hasNamePropertyUsage = (binding) => {
|
|
65
|
+
return binding.referencePaths.some((referencePath) => {
|
|
66
|
+
if (!referencePath.isIdentifier())
|
|
67
|
+
return false;
|
|
68
|
+
const objectPath = unwrapTransparentExpressionPath(referencePath);
|
|
69
|
+
const parentPath = objectPath.parentPath;
|
|
70
|
+
if ((!parentPath.isMemberExpression() &&
|
|
71
|
+
!parentPath.isOptionalMemberExpression()) ||
|
|
72
|
+
parentPath.node.object !== objectPath.node) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return getMemberPropertyName(parentPath.node) === "name";
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
export const isDirentCallbackParameterBinding = (binding) => {
|
|
79
|
+
const bindingPath = binding.path;
|
|
80
|
+
if (!bindingPath.isIdentifier())
|
|
81
|
+
return false;
|
|
82
|
+
const callbackPath = bindingPath.parentPath;
|
|
83
|
+
if (!callbackPath.isFunctionExpression() &&
|
|
84
|
+
!callbackPath.isArrowFunctionExpression()) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const [firstParameter] = callbackPath.node.params;
|
|
88
|
+
if (firstParameter?.type !== "Identifier")
|
|
89
|
+
return false;
|
|
90
|
+
if (firstParameter !== binding.identifier)
|
|
91
|
+
return false;
|
|
92
|
+
const callbackContainerPath = unwrapTransparentExpressionPath(callbackPath);
|
|
93
|
+
const callbackCallPath = callbackContainerPath.parentPath;
|
|
94
|
+
if (!callbackCallPath.isCallExpression() &&
|
|
95
|
+
!callbackCallPath.isOptionalCallExpression()) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if (!isIterableCallbackCall(callbackCallPath))
|
|
99
|
+
return false;
|
|
100
|
+
// Require reading dirent.name somewhere in the callback to avoid Stats-like false positives.
|
|
101
|
+
if (!hasNamePropertyUsage(binding))
|
|
102
|
+
return false;
|
|
103
|
+
const [firstArgument] = callbackCallPath.node.arguments;
|
|
104
|
+
if (!firstArgument)
|
|
105
|
+
return false;
|
|
106
|
+
if (firstArgument.type === "SpreadElement")
|
|
107
|
+
return false;
|
|
108
|
+
if (firstArgument.type === "ArgumentPlaceholder")
|
|
109
|
+
return false;
|
|
110
|
+
return unwrapTransparentExpressionNode(firstArgument) === callbackPath.node;
|
|
111
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getMemberPropertyName, } from "./get-member-property-name.js";
|
|
2
|
+
const direntMethodNames = new Set([
|
|
3
|
+
"isBlockDevice",
|
|
4
|
+
"isCharacterDevice",
|
|
5
|
+
"isDirectory",
|
|
6
|
+
"isFIFO",
|
|
7
|
+
"isFile",
|
|
8
|
+
"isSocket",
|
|
9
|
+
"isSymbolicLink",
|
|
10
|
+
]);
|
|
11
|
+
// Intentional heuristic: these names are a readability signal, not strict type inference.
|
|
12
|
+
// Additional callback-shape guards in is-dirent-callback-parameter-binding keep this conservative.
|
|
13
|
+
const isCallLikePath = (path) => {
|
|
14
|
+
return path.isCallExpression() || path.isOptionalCallExpression();
|
|
15
|
+
};
|
|
16
|
+
export const isDirentMethodCall = (path) => {
|
|
17
|
+
const propertyName = getMemberPropertyName(path.node);
|
|
18
|
+
if (!propertyName)
|
|
19
|
+
return false;
|
|
20
|
+
if (!direntMethodNames.has(propertyName))
|
|
21
|
+
return false;
|
|
22
|
+
const callPath = path.parentPath;
|
|
23
|
+
if (!isCallLikePath(callPath))
|
|
24
|
+
return false;
|
|
25
|
+
return callPath.node.callee === path.node;
|
|
26
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommended": true,
|
|
3
|
+
"notes": "stableNames counts unique `$...` identifiers in transformed output for this transform run, so this value can differ across transforms.",
|
|
4
|
+
"evaluations": {
|
|
5
|
+
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
6
|
+
"diffSizePercent": 100,
|
|
7
|
+
"evaluatedAt": "2026-02-06T21:03:02.730Z",
|
|
8
|
+
"changedLines": 518,
|
|
9
|
+
"durationSeconds": 177.77177340999998,
|
|
10
|
+
"stableNames": 1360
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
|
|
3
|
+
import { getFilesToProcess, } from "../../core/types.js";
|
|
4
|
+
import { hasDynamicNameLookup } from "../has-dynamic-name-lookup.js";
|
|
5
|
+
import {} from "./get-member-property-name.js";
|
|
6
|
+
import { isDirentCallbackParameterBinding } from "./is-dirent-callback-parameter-binding.js";
|
|
7
|
+
import { isDirentMethodCall } from "./is-dirent-method-call.js";
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
10
|
+
const traverse = require("@babel/traverse").default;
|
|
11
|
+
const addDirentBinding = (path, group, seenBindings) => {
|
|
12
|
+
if (!isDirentMethodCall(path))
|
|
13
|
+
return;
|
|
14
|
+
const object = path.node.object;
|
|
15
|
+
if (object.type !== "Identifier")
|
|
16
|
+
return;
|
|
17
|
+
const binding = path.scope.getBinding(object.name);
|
|
18
|
+
if (!binding)
|
|
19
|
+
return;
|
|
20
|
+
// Reassigned parameters may stop representing a dirent in the same scope.
|
|
21
|
+
if (!binding.constant)
|
|
22
|
+
return;
|
|
23
|
+
if (!isDirentCallbackParameterBinding(binding))
|
|
24
|
+
return;
|
|
25
|
+
if (seenBindings.has(binding))
|
|
26
|
+
return;
|
|
27
|
+
const currentName = binding.identifier.name;
|
|
28
|
+
if (isStableRenamed(currentName))
|
|
29
|
+
return;
|
|
30
|
+
// Keep already-semantic names readable; we avoid adding `$` noise when intent is clear.
|
|
31
|
+
if (currentName === "dirent")
|
|
32
|
+
return;
|
|
33
|
+
group.add({
|
|
34
|
+
scope: binding.scope,
|
|
35
|
+
currentName,
|
|
36
|
+
baseName: "dirent",
|
|
37
|
+
});
|
|
38
|
+
seenBindings.add(binding);
|
|
39
|
+
};
|
|
40
|
+
export const renameDirentParametersTransform = {
|
|
41
|
+
id: "rename-dirent-parameters",
|
|
42
|
+
description: "Renames iterable callback bindings that call Dirent-style predicate methods and read .name to semantic dirent names",
|
|
43
|
+
scope: "file",
|
|
44
|
+
parallelizable: true,
|
|
45
|
+
transform(context) {
|
|
46
|
+
let nodesVisited = 0;
|
|
47
|
+
let transformationsApplied = 0;
|
|
48
|
+
for (const fileInfo of getFilesToProcess(context)) {
|
|
49
|
+
if (hasDynamicNameLookup(fileInfo.ast))
|
|
50
|
+
continue;
|
|
51
|
+
const group = new RenameGroup();
|
|
52
|
+
const seenBindings = new Set();
|
|
53
|
+
traverse(fileInfo.ast, {
|
|
54
|
+
MemberExpression(path) {
|
|
55
|
+
nodesVisited++;
|
|
56
|
+
addDirentBinding(path, group, seenBindings);
|
|
57
|
+
},
|
|
58
|
+
OptionalMemberExpression(path) {
|
|
59
|
+
nodesVisited++;
|
|
60
|
+
addDirentBinding(path, group, seenBindings);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
transformationsApplied += group.apply();
|
|
64
|
+
}
|
|
65
|
+
return Promise.resolve({
|
|
66
|
+
nodesVisited,
|
|
67
|
+
transformationsApplied,
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -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,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-
|
|
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;
|
package/dist/transforms/{is-require-from-url-module.js → shared/node/is-node-require-in-scope.js}
RENAMED
|
@@ -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 {
|
|
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
|
|
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
|
-
*
|
|
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.
|
|
5
|
+
"version": "1.94.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",
|
|
File without changes
|
/package/dist/transforms/{get-url-construction-kind.js → shared/url/get-url-construction-kind.js}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|