miniread 1.102.1 → 1.103.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/preset-stats.json +2 -2
- package/dist/transforms/shared/would-capture-referenced-outer-binding.d.ts +2 -0
- package/dist/transforms/shared/would-capture-referenced-outer-binding.js +14 -0
- package/dist/transforms-by-id/expand-boolean-literals/detect-global-boolean-rebinding.d.ts +2 -0
- package/dist/transforms-by-id/expand-boolean-literals/detect-global-boolean-rebinding.js +55 -0
- package/dist/transforms-by-id/expand-boolean-literals/expand-boolean-literals-transform.js +32 -59
- package/dist/transforms-by-id/expand-boolean-literals/manifest.json +6 -6
- package/dist/transforms-by-id/expand-boolean-literals/resolve-literal-boolean-value.d.ts +10 -0
- package/dist/transforms-by-id/expand-boolean-literals/resolve-literal-boolean-value.js +86 -0
- package/dist/transforms-by-id/expand-sequence-expressions-v5/expand-sequence-expressions-v5-transform.js +15 -0
- package/dist/transforms-by-id/expand-sequence-expressions-v5/expand-variable-declaration-sequence.js +50 -8
- package/dist/transforms-by-id/expand-sequence-expressions-v5/manifest.json +7 -7
- package/dist/transforms-by-id/expand-sequence-expressions-v5/try-expand-for-statement-init-sequence.d.ts +13 -0
- package/dist/transforms-by-id/expand-sequence-expressions-v5/try-expand-for-statement-init-sequence.js +110 -0
- package/dist/transforms-by-id/remove-redundant-else/does-jump-interrupt-boundary.d.ts +5 -0
- package/dist/transforms-by-id/remove-redundant-else/does-jump-interrupt-boundary.js +70 -0
- package/dist/transforms-by-id/remove-redundant-else/manifest.json +6 -6
- package/dist/transforms-by-id/remove-redundant-else/remove-redundant-else-transform.js +58 -32
- package/dist/transforms-by-id/rename-add-event-listener-parameters/has-event-handler-usage.js +1 -1
- package/dist/transforms-by-id/rename-add-event-listener-parameters/has-event-name-comparison.js +94 -5
- package/dist/transforms-by-id/rename-add-event-listener-parameters/manifest.json +6 -6
- package/dist/transforms-by-id/rename-add-event-listener-parameters/rename-add-event-listener-parameters-transform.js +3 -4
- package/dist/transforms-by-id/rename-asap-wrappers/get-asap-wrapper-details.d.ts +5 -0
- package/dist/transforms-by-id/rename-asap-wrappers/get-asap-wrapper-details.js +116 -0
- package/dist/transforms-by-id/rename-asap-wrappers/manifest.json +5 -5
- package/dist/transforms-by-id/rename-asap-wrappers/rename-asap-wrappers-transform.js +58 -66
- package/dist/transforms-by-id/rename-awaiter-helper-functions/apply-awaiter-helper-renames.d.ts +6 -0
- package/dist/transforms-by-id/rename-awaiter-helper-functions/apply-awaiter-helper-renames.js +103 -0
- package/dist/transforms-by-id/rename-awaiter-helper-functions/manifest.json +7 -7
- package/dist/transforms-by-id/rename-awaiter-helper-functions/match-awaiter-helper-function.d.ts +7 -2
- package/dist/transforms-by-id/rename-awaiter-helper-functions/match-awaiter-helper-function.js +20 -11
- package/dist/transforms-by-id/rename-awaiter-helper-functions/match-awaiter-helper-pattern.js +57 -23
- package/dist/transforms-by-id/rename-awaiter-helper-functions/match-awaiter-step-function.d.ts +7 -2
- package/dist/transforms-by-id/rename-awaiter-helper-functions/match-awaiter-step-function.js +19 -10
- package/dist/transforms-by-id/rename-awaiter-helper-functions/rename-awaiter-helper-functions-transform.js +2 -38
- package/dist/transforms-by-id/rename-buffer-variables/is-allowed-buffer-binding.d.ts +3 -0
- package/dist/transforms-by-id/rename-buffer-variables/is-allowed-buffer-binding.js +108 -0
- package/dist/transforms-by-id/rename-buffer-variables/is-allowed-buffer-factory-call.d.ts +3 -0
- package/dist/transforms-by-id/rename-buffer-variables/is-allowed-buffer-factory-call.js +95 -0
- package/dist/transforms-by-id/rename-buffer-variables/manifest.json +7 -7
- package/dist/transforms-by-id/rename-buffer-variables/rename-buffer-variables-transform.js +4 -100
- package/dist/transforms-by-id/rename-comparison-flags-v2/manifest.json +7 -7
- package/dist/transforms-by-id/rename-comparison-flags-v2/rename-comparison-flags-v2-transform.js +13 -7
- package/dist/transforms-by-id/rename-default-options-parameters-v3/manifest.json +6 -6
- package/dist/transforms-by-id/rename-deferred-resolve-parameters-v2/has-executor-local-dynamic-name-lookup.d.ts +2 -0
- package/dist/transforms-by-id/rename-deferred-resolve-parameters-v2/has-executor-local-dynamic-name-lookup.js +37 -0
- package/dist/transforms-by-id/rename-deferred-resolve-parameters-v2/manifest.json +7 -7
- package/dist/transforms-by-id/rename-deferred-resolve-parameters-v2/rename-deferred-resolve-parameters-v2-transform.js +16 -12
- package/dist/transforms-by-id/rename-error-first-callback-parameters-v2/has-named-direct-branch-call-argument-reference.d.ts +1 -1
- package/dist/transforms-by-id/rename-error-first-callback-parameters-v2/has-named-direct-branch-call-argument-reference.js +3 -1
- package/dist/transforms-by-id/rename-error-first-callback-parameters-v2/manifest.json +6 -6
- package/dist/transforms-by-id/rename-error-first-callback-parameters-v2/match-error-first-reject-resolve-pattern.js +42 -4
- package/dist/transforms-by-id/rename-error-first-callback-parameters-v2/rename-error-first-callback-parameters-v2-transform.js +1 -1
- package/dist/transforms-by-id/rename-error-variables/get-binding-key.d.ts +2 -0
- package/dist/transforms-by-id/rename-error-variables/get-binding-key.js +5 -0
- package/dist/transforms-by-id/rename-error-variables/manifest.json +7 -14
- package/dist/transforms-by-id/rename-error-variables/match-error-constructor.d.ts +13 -0
- package/dist/transforms-by-id/rename-error-variables/match-error-constructor.js +69 -0
- package/dist/transforms-by-id/rename-error-variables/rename-error-variables-transform.js +41 -32
- package/dist/transforms-by-id/rename-event-parameters/event-parameter-usage.js +18 -3
- package/dist/transforms-by-id/rename-event-parameters/event-property-names.d.ts +2 -0
- package/dist/transforms-by-id/rename-event-parameters/event-property-names.js +15 -0
- package/dist/transforms-by-id/rename-event-parameters/manifest.json +7 -14
- package/dist/transforms-by-id/rename-file-reader-variables/get-file-reader-event-handler-name.d.ts +9 -0
- package/dist/transforms-by-id/rename-file-reader-variables/get-file-reader-event-handler-name.js +58 -0
- package/dist/transforms-by-id/rename-file-reader-variables/get-file-reader-handler-function.d.ts +4 -0
- package/dist/transforms-by-id/rename-file-reader-variables/get-file-reader-handler-function.js +13 -0
- package/dist/transforms-by-id/rename-file-reader-variables/insert-file-reader-event-parameter.d.ts +3 -0
- package/dist/transforms-by-id/rename-file-reader-variables/insert-file-reader-event-parameter.js +25 -0
- package/dist/transforms-by-id/rename-file-reader-variables/is-file-reader-constructor.js +18 -4
- package/dist/transforms-by-id/rename-file-reader-variables/manifest.json +6 -6
- package/dist/transforms-by-id/rename-file-reader-variables/queue-file-reader-event-rename.d.ts +1 -1
- package/dist/transforms-by-id/rename-file-reader-variables/queue-file-reader-event-rename.js +67 -32
- package/dist/transforms-by-id/rename-file-reader-variables/rename-file-reader-variables-transform.js +12 -1
- package/dist/transforms-by-id/rename-fs-sync-variables/dynamic-lookup-safety.d.ts +9 -0
- package/dist/transforms-by-id/rename-fs-sync-variables/dynamic-lookup-safety.js +56 -0
- package/dist/transforms-by-id/rename-fs-sync-variables/manifest.json +9 -9
- package/dist/transforms-by-id/rename-fs-sync-variables/rename-fs-sync-variables-transform.js +18 -12
- package/dist/transforms-by-id/rename-http-server-parameters/analyze-parameters.d.ts +4 -0
- package/dist/transforms-by-id/rename-http-server-parameters/analyze-parameters.js +16 -0
- package/dist/transforms-by-id/rename-http-server-parameters/detect-create-server-callee.d.ts +2 -0
- package/dist/transforms-by-id/rename-http-server-parameters/detect-create-server-callee.js +13 -0
- package/dist/transforms-by-id/rename-http-server-parameters/detector.d.ts +2 -0
- package/dist/transforms-by-id/rename-http-server-parameters/detector.js +9 -0
- package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-argument-path.d.ts +4 -0
- package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-argument-path.js +23 -0
- package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-request-event-registration.d.ts +4 -0
- package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-request-event-registration.js +14 -0
- package/dist/transforms-by-id/rename-http-server-parameters/handlers.d.ts +6 -0
- package/dist/transforms-by-id/rename-http-server-parameters/handlers.js +47 -0
- package/dist/transforms-by-id/rename-http-server-parameters/manifest.json +6 -6
- package/dist/transforms-by-id/rename-http-server-parameters/rename-http-server-parameters-transform.js +41 -51
- package/dist/transforms-by-id/rename-http-server-parameters/validate-listener.d.ts +8 -0
- package/dist/transforms-by-id/rename-http-server-parameters/validate-listener.js +16 -0
- package/dist/transforms-by-id/rename-loop-index-variables-v3/get-loop-counter-name.js +35 -7
- package/dist/transforms-by-id/rename-loop-index-variables-v3/manifest.json +6 -6
- package/dist/transforms-by-id/rename-map-by-id-variables/has-local-dynamic-name-lookup.d.ts +3 -0
- package/dist/transforms-by-id/rename-map-by-id-variables/has-local-dynamic-name-lookup.js +37 -0
- package/dist/transforms-by-id/rename-map-by-id-variables/manifest.json +7 -7
- package/dist/transforms-by-id/rename-map-by-id-variables/rename-map-by-id-variables-transform.js +3 -3
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/get-reduce-parameter-identifier.d.ts +2 -0
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/get-reduce-parameter-identifier.js +12 -0
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/is-object-keys-reduce-call.d.ts +2 -0
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/is-object-keys-reduce-call.js +52 -0
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/manifest.json +5 -5
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/rename-object-keys-reducer-parameters-transform.js +77 -98
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/should-skip-reduce-initial-value.d.ts +2 -0
- package/dist/transforms-by-id/rename-object-keys-reducer-parameters/should-skip-reduce-initial-value.js +2 -0
- package/dist/transforms-by-id/rename-object-keys-variables/is-safe-keys-reassignment.d.ts +7 -0
- package/dist/transforms-by-id/rename-object-keys-variables/is-safe-keys-reassignment.js +96 -0
- package/dist/transforms-by-id/rename-object-keys-variables/manifest.json +7 -7
- package/dist/transforms-by-id/rename-object-keys-variables/rename-object-keys-variables-transform.js +11 -34
- package/dist/transforms-by-id/rename-promise-executor-parameters-v2/get-promise-executor-rename-plan.d.ts +13 -0
- package/dist/transforms-by-id/rename-promise-executor-parameters-v2/get-promise-executor-rename-plan.js +102 -0
- package/dist/transforms-by-id/rename-promise-executor-parameters-v2/manifest.json +6 -6
- package/dist/transforms-by-id/rename-promise-executor-parameters-v2/promise-executor-heuristics.d.ts +3 -0
- package/dist/transforms-by-id/rename-promise-executor-parameters-v2/promise-executor-heuristics.js +26 -0
- package/dist/transforms-by-id/rename-promise-executor-parameters-v2/rename-promise-executor-parameters-v2-transform.js +8 -86
- package/dist/transforms-by-id/rename-range-parameters/get-count-default-assignment.d.ts +2 -0
- package/dist/transforms-by-id/rename-range-parameters/get-count-default-assignment.js +27 -0
- package/dist/transforms-by-id/rename-range-parameters/get-explicit-start-count-method-usage.js +29 -13
- package/dist/transforms-by-id/rename-range-parameters/get-range-parameter-names.d.ts +1 -5
- package/dist/transforms-by-id/rename-range-parameters/get-range-parameter-names.js +24 -113
- package/dist/transforms-by-id/rename-range-parameters/get-range-parameters-from-pair.d.ts +13 -0
- package/dist/transforms-by-id/rename-range-parameters/get-range-parameters-from-pair.js +124 -0
- package/dist/transforms-by-id/rename-range-parameters/has-start-count-loop-boundary-usage.js +2 -2
- package/dist/transforms-by-id/rename-range-parameters/is-nullish-parameter-check.d.ts +3 -0
- package/dist/transforms-by-id/rename-range-parameters/is-nullish-parameter-check.js +23 -0
- package/dist/transforms-by-id/rename-range-parameters/is-start-count-sum-expression.d.ts +1 -1
- package/dist/transforms-by-id/rename-range-parameters/is-start-count-sum-expression.js +19 -1
- package/dist/transforms-by-id/rename-range-parameters/manifest.json +6 -6
- package/dist/transforms-by-id/rename-regex-source-parameters/manifest.json +6 -6
- package/dist/transforms-by-id/rename-regex-source-parameters/match-direct-source-accessor.d.ts +4 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/match-direct-source-accessor.js +27 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/match-regex-source-normalizer-with-guards.d.ts +4 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/match-regex-source-normalizer-with-guards.js +104 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/match-regex-source-normalizer.d.ts +4 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/match-regex-source-normalizer.js +3 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/regex-source-normalizer-shared.d.ts +9 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/regex-source-normalizer-shared.js +46 -0
- package/dist/transforms-by-id/rename-regex-source-parameters/rename-regex-source-parameters-transform.js +3 -87
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-destructure-usage.d.ts +2 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/{search-parameters-usage-heuristics.js → is-search-parameters-destructure-usage.js} +27 -104
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-for-of-usage.d.ts +2 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-for-of-usage.js +18 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-property-access.d.ts +2 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-property-access.js +30 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-spread-usage.d.ts +2 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/is-search-parameters-spread-usage.js +34 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/manifest.json +6 -13
- package/dist/transforms-by-id/rename-search-parameters-variables/rename-search-parameters-variables-transform.js +33 -19
- package/dist/transforms-by-id/rename-search-parameters-variables/search-parameters-property-names.d.ts +1 -0
- package/dist/transforms-by-id/rename-search-parameters-variables/search-parameters-property-names.js +15 -0
- package/dist/transforms-by-id/rename-string-split-variables-v2/manifest.json +8 -8
- package/dist/transforms-by-id/rename-string-split-variables-v2/rename-string-split-variables-v2-transform.js +33 -10
- package/dist/transforms-by-id/rename-timeout-promises/is-global-set-timeout-alias.d.ts +2 -0
- package/dist/transforms-by-id/rename-timeout-promises/is-global-set-timeout-alias.js +67 -0
- package/dist/transforms-by-id/rename-timeout-promises/is-safe-global-object-expression-for-set-timeout-alias.d.ts +3 -0
- package/dist/transforms-by-id/rename-timeout-promises/is-safe-global-object-expression-for-set-timeout-alias.js +39 -0
- package/dist/transforms-by-id/rename-timeout-promises/manifest.json +7 -7
- package/dist/transforms-by-id/rename-timeout-promises/rename-timeout-promises-transform.js +66 -56
- package/dist/transforms-by-id/rename-timeout-promises/set-timeout-usage.d.ts +3 -0
- package/dist/transforms-by-id/rename-timeout-promises/set-timeout-usage.js +40 -0
- package/dist/transforms-by-id/rename-typeof-variables/manifest.json +0 -7
- package/dist/transforms-by-id/rename-url-parameters/manifest.json +6 -13
- package/dist/transforms-by-id/rename-url-parameters/rename-url-parameters-transform.js +13 -15
- package/dist/transforms-by-id/rename-url-parameters/url-parameter-rename-overlap.d.ts +3 -0
- package/dist/transforms-by-id/rename-url-parameters/url-parameter-rename-overlap.js +72 -0
- package/dist/transforms-by-id/rename-url-variables/manifest.json +0 -7
- package/dist/transforms-by-id/simplify-boolean-negations/manifest.json +6 -6
- package/dist/transforms-by-id/simplify-boolean-negations/simplify-boolean-negations-transform.js +46 -2
- package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/collect-deferred-variables.d.ts +1 -0
- package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/collect-deferred-variables.js +14 -8
- package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/manifest.json +8 -8
- package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/rename-helpers.js +8 -1
- package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/stabilize-deferred-top-level-bindings-transform.js +3 -2
- package/dist/transforms-by-id/use-object-property-shorthand/manifest.json +6 -6
- package/dist/transforms-by-id/use-object-property-shorthand/use-object-property-shorthand-transform.js +16 -2
- package/dist/transforms-by-id/use-object-shorthand/is-for-in-or-of-assignment-head.d.ts +3 -0
- package/dist/transforms-by-id/use-object-shorthand/is-for-in-or-of-assignment-head.js +16 -0
- package/dist/transforms-by-id/use-object-shorthand/manifest.json +9 -9
- package/dist/transforms-by-id/use-object-shorthand/use-object-shorthand-transform.js +95 -21
- package/dist/transforms-by-id/use-object-shorthand/would-capture-target-name-references.d.ts +2 -0
- package/dist/transforms-by-id/use-object-shorthand/would-capture-target-name-references.js +23 -0
- package/package.json +16 -16
- package/dist/transforms-by-id/rename-range-parameters/has-start-count-sum.d.ts +0 -3
- package/dist/transforms-by-id/rename-range-parameters/has-start-count-sum.js +0 -34
- package/dist/transforms-by-id/rename-search-parameters-variables/search-parameters-usage-heuristics.d.ts +0 -5
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const wouldCaptureReferencedOuterBinding = (bindingScope, targetName) => {
|
|
2
|
+
if (bindingScope.path.isProgram())
|
|
3
|
+
return false;
|
|
4
|
+
const outerBinding = bindingScope.parent.getBinding(targetName);
|
|
5
|
+
if (!outerBinding)
|
|
6
|
+
return false;
|
|
7
|
+
const outerUsagePaths = [
|
|
8
|
+
...outerBinding.referencePaths,
|
|
9
|
+
...outerBinding.constantViolations,
|
|
10
|
+
];
|
|
11
|
+
return outerUsagePaths.some((usagePath) => {
|
|
12
|
+
return usagePath.isDescendant(bindingScope.path);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
4
|
+
const traverse = require("@babel/traverse").default;
|
|
5
|
+
const GLOBAL_OBJECT_NAMES = new Set(["globalThis", "global", "window", "self"]);
|
|
6
|
+
const isGlobalBooleanMemberExpression = (node) => {
|
|
7
|
+
if (node.object.type !== "Identifier")
|
|
8
|
+
return false;
|
|
9
|
+
if (!GLOBAL_OBJECT_NAMES.has(node.object.name))
|
|
10
|
+
return false;
|
|
11
|
+
if (!node.computed) {
|
|
12
|
+
return (node.property.type === "Identifier" && node.property.name === "Boolean");
|
|
13
|
+
}
|
|
14
|
+
return (node.property.type === "StringLiteral" && node.property.value === "Boolean");
|
|
15
|
+
};
|
|
16
|
+
export const hasGlobalBooleanRebinding = (ast) => {
|
|
17
|
+
let foundGlobalBooleanRebinding = false;
|
|
18
|
+
traverse(ast, {
|
|
19
|
+
AssignmentExpression(path) {
|
|
20
|
+
if (foundGlobalBooleanRebinding)
|
|
21
|
+
return;
|
|
22
|
+
const { left } = path.node;
|
|
23
|
+
if (left.type === "Identifier" && left.name === "Boolean") {
|
|
24
|
+
if (!path.scope.hasBinding("Boolean", true)) {
|
|
25
|
+
foundGlobalBooleanRebinding = true;
|
|
26
|
+
path.stop();
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (left.type === "MemberExpression" &&
|
|
31
|
+
isGlobalBooleanMemberExpression(left)) {
|
|
32
|
+
foundGlobalBooleanRebinding = true;
|
|
33
|
+
path.stop();
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
UpdateExpression(path) {
|
|
37
|
+
if (foundGlobalBooleanRebinding)
|
|
38
|
+
return;
|
|
39
|
+
const { argument } = path.node;
|
|
40
|
+
if (argument.type === "Identifier" && argument.name === "Boolean") {
|
|
41
|
+
if (!path.scope.hasBinding("Boolean", true)) {
|
|
42
|
+
foundGlobalBooleanRebinding = true;
|
|
43
|
+
path.stop();
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (argument.type === "MemberExpression" &&
|
|
48
|
+
isGlobalBooleanMemberExpression(argument)) {
|
|
49
|
+
foundGlobalBooleanRebinding = true;
|
|
50
|
+
path.stop();
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return foundGlobalBooleanRebinding;
|
|
55
|
+
};
|
|
@@ -1,58 +1,11 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { getFilesToProcess, } from "../../core/types.js";
|
|
3
|
+
import { hasGlobalBooleanRebinding } from "./detect-global-boolean-rebinding.js";
|
|
4
|
+
import { resolveBooleanNegationValue, resolveDoubleNegationValue, } from "./resolve-literal-boolean-value.js";
|
|
3
5
|
const require = createRequire(import.meta.url);
|
|
4
6
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
5
7
|
const traverse = require("@babel/traverse").default;
|
|
6
8
|
const t = require("@babel/types");
|
|
7
|
-
const GLOBAL_OBJECT_NAMES = new Set(["globalThis", "global", "window", "self"]);
|
|
8
|
-
const isGlobalBooleanMemberExpression = (node) => {
|
|
9
|
-
if (node.object.type !== "Identifier") {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
if (!GLOBAL_OBJECT_NAMES.has(node.object.name)) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
if (!node.computed) {
|
|
16
|
-
return (node.property.type === "Identifier" && node.property.name === "Boolean");
|
|
17
|
-
}
|
|
18
|
-
return (node.property.type === "StringLiteral" && node.property.value === "Boolean");
|
|
19
|
-
};
|
|
20
|
-
const hasGlobalBooleanRebinding = (ast) => {
|
|
21
|
-
let globalBooleanRebound = false;
|
|
22
|
-
traverse(ast, {
|
|
23
|
-
AssignmentExpression(path) {
|
|
24
|
-
const { left } = path.node;
|
|
25
|
-
if (left.type === "Identifier" && left.name === "Boolean") {
|
|
26
|
-
if (!path.scope.hasBinding("Boolean", true)) {
|
|
27
|
-
globalBooleanRebound = true;
|
|
28
|
-
path.stop();
|
|
29
|
-
}
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (left.type === "MemberExpression" &&
|
|
33
|
-
isGlobalBooleanMemberExpression(left)) {
|
|
34
|
-
globalBooleanRebound = true;
|
|
35
|
-
path.stop();
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
UpdateExpression(path) {
|
|
39
|
-
const { argument } = path.node;
|
|
40
|
-
if (argument.type === "Identifier" && argument.name === "Boolean") {
|
|
41
|
-
if (!path.scope.hasBinding("Boolean", true)) {
|
|
42
|
-
globalBooleanRebound = true;
|
|
43
|
-
path.stop();
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (argument.type === "MemberExpression" &&
|
|
48
|
-
isGlobalBooleanMemberExpression(argument)) {
|
|
49
|
-
globalBooleanRebound = true;
|
|
50
|
-
path.stop();
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
return globalBooleanRebound;
|
|
55
|
-
};
|
|
56
9
|
export const expandBooleanLiteralsTransform = {
|
|
57
10
|
id: "expand-boolean-literals",
|
|
58
11
|
description: "Expands !0 to true and !1 to false",
|
|
@@ -62,7 +15,7 @@ export const expandBooleanLiteralsTransform = {
|
|
|
62
15
|
let nodesVisited = 0;
|
|
63
16
|
let transformationsApplied = 0;
|
|
64
17
|
for (const fileInfo of getFilesToProcess(context)) {
|
|
65
|
-
const
|
|
18
|
+
const hasGlobalBooleanRebindingInFile = hasGlobalBooleanRebinding(fileInfo.ast);
|
|
66
19
|
traverse(fileInfo.ast, {
|
|
67
20
|
UnaryExpression(path) {
|
|
68
21
|
nodesVisited++;
|
|
@@ -70,34 +23,54 @@ export const expandBooleanLiteralsTransform = {
|
|
|
70
23
|
if (operator !== "!") {
|
|
71
24
|
return;
|
|
72
25
|
}
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
26
|
+
if (path.findParent((parentPath) => parentPath.isWithStatement())) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const booleanNegationResolution = resolveBooleanNegationValue(path, argument);
|
|
30
|
+
if (booleanNegationResolution !== undefined) {
|
|
31
|
+
if (booleanNegationResolution.kind === "literal" &&
|
|
32
|
+
!path.get("argument").isPure()) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
path.replaceWith(t.booleanLiteral(booleanNegationResolution.value));
|
|
77
36
|
transformationsApplied++;
|
|
78
37
|
return;
|
|
79
38
|
}
|
|
80
39
|
if (argument.type === "UnaryExpression" &&
|
|
81
40
|
argument.operator === "!" &&
|
|
82
41
|
argument.argument.type === "NumericLiteral") {
|
|
83
|
-
// !!0 = false, !!1 = true, !!2 = true
|
|
84
42
|
const booleanValue = argument.argument.value !== 0;
|
|
85
43
|
path.replaceWith(t.booleanLiteral(booleanValue));
|
|
86
44
|
transformationsApplied++;
|
|
87
45
|
return;
|
|
88
46
|
}
|
|
47
|
+
if (argument.type === "BinaryExpression" &&
|
|
48
|
+
(argument.operator === "in" || argument.operator === "instanceof")) {
|
|
49
|
+
path.replaceWith(t.binaryExpression("===", t.parenthesizedExpression(t.cloneNode(argument, true)), t.booleanLiteral(false)));
|
|
50
|
+
transformationsApplied++;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
89
53
|
if (argument.type === "UnaryExpression" &&
|
|
90
54
|
argument.operator === "!") {
|
|
91
|
-
|
|
55
|
+
const doubleNegationResolution = resolveDoubleNegationValue(path, argument.argument);
|
|
56
|
+
if (doubleNegationResolution !== undefined) {
|
|
57
|
+
if (doubleNegationResolution.kind === "literal" &&
|
|
58
|
+
!path.get("argument.argument").isPure()) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
path.replaceWith(t.booleanLiteral(doubleNegationResolution.value));
|
|
62
|
+
transformationsApplied++;
|
|
92
63
|
return;
|
|
93
64
|
}
|
|
94
|
-
|
|
65
|
+
}
|
|
66
|
+
if (argument.type === "UnaryExpression" &&
|
|
67
|
+
argument.operator === "!") {
|
|
68
|
+
if (path.scope.hasBinding("Boolean", true)) {
|
|
95
69
|
return;
|
|
96
70
|
}
|
|
97
|
-
if (
|
|
71
|
+
if (hasGlobalBooleanRebindingInFile) {
|
|
98
72
|
return;
|
|
99
73
|
}
|
|
100
|
-
// !!value = Boolean(value) when Boolean isn't shadowed
|
|
101
74
|
path.replaceWith(t.callExpression(t.identifier("Boolean"), [
|
|
102
75
|
t.cloneNode(argument.argument, true),
|
|
103
76
|
]));
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Improves readability but does not reduce diffs (boolean literals are already deterministic)",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
5
|
"diffSizePercent": 100,
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds": 40.
|
|
6
|
+
"evaluatedAt": "2026-02-10T20:27:40.370Z",
|
|
7
|
+
"changedLines": 37534,
|
|
8
|
+
"durationSeconds": 40.372261375,
|
|
11
9
|
"stableNames": 1357
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type * as BabelTypes from "@babel/types";
|
|
3
|
+
import type { UnaryExpression } from "@babel/types";
|
|
4
|
+
type ResolvedBooleanValue = {
|
|
5
|
+
kind: "literal" | "global-identifier" | "const-identifier";
|
|
6
|
+
value: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare const resolveBooleanNegationValue: (path: NodePath<UnaryExpression>, argument: BabelTypes.Expression) => ResolvedBooleanValue | undefined;
|
|
9
|
+
export declare const resolveDoubleNegationValue: (path: NodePath<UnaryExpression>, argument: BabelTypes.Expression) => ResolvedBooleanValue | undefined;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const getLiteralBooleanValue = (node) => {
|
|
2
|
+
if (node.type === "NumericLiteral")
|
|
3
|
+
return node.value !== 0;
|
|
4
|
+
if (node.type === "BigIntLiteral")
|
|
5
|
+
return BigInt(node.value) !== 0n;
|
|
6
|
+
if (node.type === "StringLiteral")
|
|
7
|
+
return node.value.length > 0;
|
|
8
|
+
if (node.type === "BooleanLiteral")
|
|
9
|
+
return node.value;
|
|
10
|
+
if (node.type === "NullLiteral")
|
|
11
|
+
return false;
|
|
12
|
+
if (node.type === "UnaryExpression") {
|
|
13
|
+
return node.operator === "void" ? false : undefined;
|
|
14
|
+
}
|
|
15
|
+
if (node.type === "ArrayExpression" ||
|
|
16
|
+
node.type === "ObjectExpression" ||
|
|
17
|
+
node.type === "FunctionExpression" ||
|
|
18
|
+
node.type === "ArrowFunctionExpression" ||
|
|
19
|
+
node.type === "ClassExpression" ||
|
|
20
|
+
node.type === "RegExpLiteral") {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
};
|
|
25
|
+
const getGlobalIdentifierBooleanValue = (path, node) => {
|
|
26
|
+
if (node.type !== "Identifier")
|
|
27
|
+
return undefined;
|
|
28
|
+
if (path.scope.hasBinding(node.name, true))
|
|
29
|
+
return undefined;
|
|
30
|
+
if (node.name === "NaN")
|
|
31
|
+
return false;
|
|
32
|
+
if (node.name === "Infinity")
|
|
33
|
+
return true;
|
|
34
|
+
return undefined;
|
|
35
|
+
};
|
|
36
|
+
const getConstIdentifierBooleanValue = (path, node) => {
|
|
37
|
+
if (node.type !== "Identifier")
|
|
38
|
+
return undefined;
|
|
39
|
+
const binding = path.scope.getBinding(node.name);
|
|
40
|
+
if (binding?.kind !== "const")
|
|
41
|
+
return undefined;
|
|
42
|
+
if (!binding.path.isVariableDeclarator())
|
|
43
|
+
return undefined;
|
|
44
|
+
const declarationEnd = binding.path.node.end;
|
|
45
|
+
const expressionStart = path.node.start;
|
|
46
|
+
if (declarationEnd === undefined ||
|
|
47
|
+
declarationEnd === null ||
|
|
48
|
+
expressionStart === undefined ||
|
|
49
|
+
expressionStart === null ||
|
|
50
|
+
declarationEnd >= expressionStart) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const initializer = binding.path.node.init;
|
|
54
|
+
if (!initializer)
|
|
55
|
+
return undefined;
|
|
56
|
+
return getLiteralBooleanValue(initializer);
|
|
57
|
+
};
|
|
58
|
+
export const resolveBooleanNegationValue = (path, argument) => {
|
|
59
|
+
const literalBooleanValue = getLiteralBooleanValue(argument);
|
|
60
|
+
if (literalBooleanValue !== undefined) {
|
|
61
|
+
return { kind: "literal", value: !literalBooleanValue };
|
|
62
|
+
}
|
|
63
|
+
const globalIdentifierBooleanValue = getGlobalIdentifierBooleanValue(path, argument);
|
|
64
|
+
if (globalIdentifierBooleanValue !== undefined) {
|
|
65
|
+
return { kind: "global-identifier", value: !globalIdentifierBooleanValue };
|
|
66
|
+
}
|
|
67
|
+
const constIdentifierBooleanValue = getConstIdentifierBooleanValue(path, argument);
|
|
68
|
+
if (constIdentifierBooleanValue !== undefined) {
|
|
69
|
+
return { kind: "const-identifier", value: !constIdentifierBooleanValue };
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
};
|
|
73
|
+
export const resolveDoubleNegationValue = (path, argument) => {
|
|
74
|
+
const literalBooleanValue = getLiteralBooleanValue(argument);
|
|
75
|
+
if (literalBooleanValue !== undefined) {
|
|
76
|
+
return { kind: "literal", value: literalBooleanValue };
|
|
77
|
+
}
|
|
78
|
+
const globalIdentifierBooleanValue = getGlobalIdentifierBooleanValue(path, argument);
|
|
79
|
+
if (globalIdentifierBooleanValue !== undefined) {
|
|
80
|
+
return { kind: "global-identifier", value: globalIdentifierBooleanValue };
|
|
81
|
+
}
|
|
82
|
+
const constIdentifierBooleanValue = getConstIdentifierBooleanValue(path, argument);
|
|
83
|
+
if (constIdentifierBooleanValue === undefined)
|
|
84
|
+
return undefined;
|
|
85
|
+
return { kind: "const-identifier", value: constIdentifierBooleanValue };
|
|
86
|
+
};
|
|
@@ -17,38 +17,53 @@ export const expandSequenceExpressionsV5Transform = {
|
|
|
17
17
|
let nodesVisited = 0;
|
|
18
18
|
let transformationsApplied = 0;
|
|
19
19
|
for (const [, fileInfo] of projectGraph.files) {
|
|
20
|
+
let fileTransformationsApplied = 0;
|
|
20
21
|
traverse(fileInfo.ast, {
|
|
21
22
|
ReturnStatement(path) {
|
|
22
23
|
nodesVisited++;
|
|
23
24
|
if (!tryExpandReturnSequence(path))
|
|
24
25
|
return;
|
|
26
|
+
fileTransformationsApplied += 1;
|
|
25
27
|
transformationsApplied += 1;
|
|
26
28
|
},
|
|
27
29
|
ThrowStatement(path) {
|
|
28
30
|
nodesVisited++;
|
|
29
31
|
if (!tryExpandThrowSequence(path))
|
|
30
32
|
return;
|
|
33
|
+
fileTransformationsApplied += 1;
|
|
31
34
|
transformationsApplied += 1;
|
|
32
35
|
},
|
|
33
36
|
ExpressionStatement(path) {
|
|
34
37
|
nodesVisited++;
|
|
35
38
|
if (!tryExpandExpressionStatementSequence(path))
|
|
36
39
|
return;
|
|
40
|
+
fileTransformationsApplied += 1;
|
|
37
41
|
transformationsApplied += 1;
|
|
38
42
|
},
|
|
39
43
|
VariableDeclaration(path) {
|
|
40
44
|
nodesVisited++;
|
|
41
45
|
if (!tryExpandVariableDeclarationSequenceInitializers(path))
|
|
42
46
|
return;
|
|
47
|
+
fileTransformationsApplied += 1;
|
|
43
48
|
transformationsApplied += 1;
|
|
44
49
|
},
|
|
45
50
|
IfStatement(path) {
|
|
46
51
|
nodesVisited++;
|
|
47
52
|
if (!tryExpandIfStatementTestSequence(path))
|
|
48
53
|
return;
|
|
54
|
+
fileTransformationsApplied += 1;
|
|
49
55
|
transformationsApplied += 1;
|
|
50
56
|
},
|
|
51
57
|
});
|
|
58
|
+
if (fileTransformationsApplied === 0)
|
|
59
|
+
continue;
|
|
60
|
+
// Keep scope bindings/reference paths in sync for downstream transforms.
|
|
61
|
+
traverse(fileInfo.ast, {
|
|
62
|
+
Program(path) {
|
|
63
|
+
path.scope.crawl();
|
|
64
|
+
path.stop();
|
|
65
|
+
},
|
|
66
|
+
});
|
|
52
67
|
}
|
|
53
68
|
return Promise.resolve({ nodesVisited, transformationsApplied });
|
|
54
69
|
},
|
package/dist/transforms-by-id/expand-sequence-expressions-v5/expand-variable-declaration-sequence.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { tryExpandForStatementInitSequence } from "./try-expand-for-statement-init-sequence.js";
|
|
2
3
|
const require = createRequire(import.meta.url);
|
|
3
4
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
4
5
|
const t = require("@babel/types");
|
|
@@ -28,7 +29,7 @@ const createVariableDeclarator = (id, init) => {
|
|
|
28
29
|
t.cloneNode(init, true)
|
|
29
30
|
: undefined);
|
|
30
31
|
};
|
|
31
|
-
const
|
|
32
|
+
const canReplaceWithMultiple = (path) => {
|
|
32
33
|
const parentPath = path.parentPath;
|
|
33
34
|
if (!parentPath)
|
|
34
35
|
return false;
|
|
@@ -37,6 +38,28 @@ const isSupportedStatementContainer = (path) => {
|
|
|
37
38
|
parentPath.isStaticBlock() ||
|
|
38
39
|
parentPath.isSwitchCase());
|
|
39
40
|
};
|
|
41
|
+
const canWrapInBlock = (path) => {
|
|
42
|
+
const parentPath = path.parentPath;
|
|
43
|
+
if (!parentPath)
|
|
44
|
+
return false;
|
|
45
|
+
if (parentPath.isLabeledStatement() && path.key === "body") {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
if (parentPath.isIfStatement() &&
|
|
49
|
+
(path.key === "consequent" || path.key === "alternate")) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if ((parentPath.isForStatement() ||
|
|
53
|
+
parentPath.isForInStatement() ||
|
|
54
|
+
parentPath.isForOfStatement() ||
|
|
55
|
+
parentPath.isWhileStatement() ||
|
|
56
|
+
parentPath.isDoWhileStatement() ||
|
|
57
|
+
parentPath.isWithStatement()) &&
|
|
58
|
+
path.key === "body") {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
};
|
|
40
63
|
const isDirectiveProloguePosition = (path) => {
|
|
41
64
|
const parentPath = path.parentPath;
|
|
42
65
|
if (!parentPath)
|
|
@@ -69,14 +92,25 @@ const isDirectiveProloguePosition = (path) => {
|
|
|
69
92
|
return true;
|
|
70
93
|
};
|
|
71
94
|
export const tryExpandVariableDeclarationSequenceInitializers = (path) => {
|
|
72
|
-
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
declarator.init.expressions.length >= 2);
|
|
95
|
+
const hasAnySequence = path.node.declarations.some((declarator) => {
|
|
96
|
+
return (declarator.init?.type === "SequenceExpression" &&
|
|
97
|
+
declarator.init.expressions.length >= 2);
|
|
98
|
+
});
|
|
77
99
|
if (!hasAnySequence)
|
|
78
100
|
return false;
|
|
79
101
|
const kind = path.node.kind;
|
|
102
|
+
if (tryExpandForStatementInitSequence(path, {
|
|
103
|
+
canReplaceWithMultiple,
|
|
104
|
+
canWrapInBlock,
|
|
105
|
+
createExpressionStatement,
|
|
106
|
+
createVariableDeclarator,
|
|
107
|
+
isDirectiveProloguePosition,
|
|
108
|
+
})) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (!canReplaceWithMultiple(path) && !canWrapInBlock(path))
|
|
112
|
+
return false;
|
|
113
|
+
const isDirectivePrologueAtInsertion = isDirectiveProloguePosition(path);
|
|
80
114
|
const statements = [];
|
|
81
115
|
for (const declarator of path.node.declarations) {
|
|
82
116
|
const init = declarator.init;
|
|
@@ -98,6 +132,14 @@ export const tryExpandVariableDeclarationSequenceInitializers = (path) => {
|
|
|
98
132
|
const newDeclarator = createVariableDeclarator(declarator.id, lastExpression);
|
|
99
133
|
statements.push(createVariableDeclarationStatement(kind, newDeclarator));
|
|
100
134
|
}
|
|
101
|
-
path
|
|
102
|
-
|
|
135
|
+
if (canReplaceWithMultiple(path)) {
|
|
136
|
+
path.replaceWithMultiple(statements);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
if (canWrapInBlock(path)) {
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
141
|
+
path.replaceWith(t.blockStatement(statements));
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
103
145
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"recommended": true,
|
|
3
|
-
"recommendedOrder": 100,
|
|
4
2
|
"notes": "Extends expand-sequence-expressions-v4 by also expanding `if ((a, b)) ...` style tests.",
|
|
5
3
|
"evaluations": {
|
|
6
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
7
|
-
"diffSizePercent": 102.
|
|
8
|
-
"evaluatedAt": "2026-02-
|
|
9
|
-
"changedLines":
|
|
10
|
-
"durationSeconds":
|
|
5
|
+
"diffSizePercent": 102.02970858373965,
|
|
6
|
+
"evaluatedAt": "2026-02-11T06:06:13.210Z",
|
|
7
|
+
"changedLines": 204853,
|
|
8
|
+
"durationSeconds": 46.743897499999996,
|
|
11
9
|
"stableNames": 1357
|
|
12
10
|
}
|
|
13
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"recommended": true,
|
|
13
|
+
"recommendedOrder": 100
|
|
14
14
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { Expression, Statement, VariableDeclaration } from "@babel/types";
|
|
3
|
+
type ForStatementInitHelpers = {
|
|
4
|
+
canReplaceWithMultiple: (path: NodePath) => boolean;
|
|
5
|
+
canWrapInBlock: (path: NodePath) => boolean;
|
|
6
|
+
createExpressionStatement: (expression: Expression, options: {
|
|
7
|
+
wrapStringLiteralDirective: boolean;
|
|
8
|
+
}) => Statement;
|
|
9
|
+
createVariableDeclarator: (id: VariableDeclaration["declarations"][number]["id"], init: VariableDeclaration["declarations"][number]["init"]) => VariableDeclaration["declarations"][number];
|
|
10
|
+
isDirectiveProloguePosition: (path: NodePath) => boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const tryExpandForStatementInitSequence: (path: NodePath<VariableDeclaration>, helpers: ForStatementInitHelpers) => boolean;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
4
|
+
const t = require("@babel/types");
|
|
5
|
+
export const tryExpandForStatementInitSequence = (path, helpers) => {
|
|
6
|
+
const parentPath = path.parentPath;
|
|
7
|
+
if (!parentPath.isForStatement())
|
|
8
|
+
return false;
|
|
9
|
+
if (path.key !== "init")
|
|
10
|
+
return false;
|
|
11
|
+
if (path.node.kind !== "var")
|
|
12
|
+
return false;
|
|
13
|
+
const sequenceDeclaratorIndices = path.node.declarations
|
|
14
|
+
.map((declarator, index) => {
|
|
15
|
+
if (declarator.init?.type !== "SequenceExpression")
|
|
16
|
+
return -1;
|
|
17
|
+
return declarator.init.expressions.length >= 2 ? index : -1;
|
|
18
|
+
})
|
|
19
|
+
.filter((index) => index !== -1);
|
|
20
|
+
if (sequenceDeclaratorIndices.length === 0)
|
|
21
|
+
return false;
|
|
22
|
+
const insertionTarget = parentPath.parentPath.isLabeledStatement()
|
|
23
|
+
? parentPath.parentPath
|
|
24
|
+
: parentPath;
|
|
25
|
+
const canReplace = helpers.canReplaceWithMultiple(insertionTarget);
|
|
26
|
+
const canWrap = helpers.canWrapInBlock(insertionTarget);
|
|
27
|
+
if (!canReplace && !canWrap)
|
|
28
|
+
return false;
|
|
29
|
+
const shouldWrapDirective = helpers.isDirectiveProloguePosition(insertionTarget);
|
|
30
|
+
const createVariableDeclarationStatement = (declarator) => {
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
32
|
+
return t.variableDeclaration(path.node.kind, [
|
|
33
|
+
helpers.createVariableDeclarator(declarator.id, declarator.init),
|
|
34
|
+
]);
|
|
35
|
+
};
|
|
36
|
+
if (sequenceDeclaratorIndices.length >= 2) {
|
|
37
|
+
const statements = [];
|
|
38
|
+
for (const declarator of path.node.declarations) {
|
|
39
|
+
const init = declarator.init;
|
|
40
|
+
if (init?.type !== "SequenceExpression") {
|
|
41
|
+
statements.push(createVariableDeclarationStatement(declarator));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const leadingExpressions = init.expressions.slice(0, -1);
|
|
45
|
+
const lastExpression = init.expressions.at(-1);
|
|
46
|
+
if (!lastExpression) {
|
|
47
|
+
statements.push(createVariableDeclarationStatement(declarator));
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
for (const expression of leadingExpressions) {
|
|
51
|
+
statements.push(helpers.createExpressionStatement(expression, {
|
|
52
|
+
wrapStringLiteralDirective: shouldWrapDirective && statements.length === 0,
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
statements.push(createVariableDeclarationStatement(helpers.createVariableDeclarator(declarator.id, lastExpression)));
|
|
56
|
+
}
|
|
57
|
+
parentPath.node.init = undefined;
|
|
58
|
+
if (canReplace) {
|
|
59
|
+
insertionTarget.insertBefore(statements);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
63
|
+
const wrappedStatement = t.blockStatement([
|
|
64
|
+
...statements,
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
66
|
+
t.cloneNode(insertionTarget.node, true),
|
|
67
|
+
]);
|
|
68
|
+
insertionTarget.replaceWith(wrappedStatement);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
const statements = [];
|
|
72
|
+
const updatedDeclarators = path.node.declarations.map((declarator) => {
|
|
73
|
+
const init = declarator.init;
|
|
74
|
+
if (init?.type !== "SequenceExpression") {
|
|
75
|
+
return helpers.createVariableDeclarator(declarator.id, init);
|
|
76
|
+
}
|
|
77
|
+
const leadingExpressions = init.expressions.slice(0, -1);
|
|
78
|
+
const lastExpression = init.expressions.at(-1);
|
|
79
|
+
if (!lastExpression) {
|
|
80
|
+
return helpers.createVariableDeclarator(declarator.id, init);
|
|
81
|
+
}
|
|
82
|
+
for (const expression of leadingExpressions) {
|
|
83
|
+
statements.push(helpers.createExpressionStatement(expression, {
|
|
84
|
+
wrapStringLiteralDirective: shouldWrapDirective && statements.length === 0,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
return helpers.createVariableDeclarator(declarator.id, lastExpression);
|
|
88
|
+
});
|
|
89
|
+
if (statements.length === 0)
|
|
90
|
+
return false;
|
|
91
|
+
const updatedInit =
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
93
|
+
t.variableDeclaration(path.node.kind, updatedDeclarators);
|
|
94
|
+
if (canReplace) {
|
|
95
|
+
parentPath.node.init = updatedInit;
|
|
96
|
+
insertionTarget.insertBefore(statements);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (!canWrap)
|
|
100
|
+
return false;
|
|
101
|
+
parentPath.node.init = updatedInit;
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
103
|
+
const wrappedStatement = t.blockStatement([
|
|
104
|
+
...statements,
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
106
|
+
t.cloneNode(insertionTarget.node, true),
|
|
107
|
+
]);
|
|
108
|
+
insertionTarget.replaceWith(wrappedStatement);
|
|
109
|
+
return true;
|
|
110
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NodePath } from "@babel/traverse";
|
|
2
|
+
import type { BreakStatement, ContinueStatement, IfStatement } from "@babel/types";
|
|
3
|
+
type JumpPath = NodePath<BreakStatement | ContinueStatement>;
|
|
4
|
+
export declare function doesJumpInterruptBoundary(jumpPath: JumpPath, boundaryIfPath: NodePath<IfStatement>): boolean;
|
|
5
|
+
export {};
|