miniread 1.119.0 → 1.120.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 (102) hide show
  1. package/dist/scripts/evaluate/compute-directory-diff.js +10 -4
  2. package/dist/transforms/preset-stats.json +2 -2
  3. package/dist/transforms-by-id/expand-boolean-literals/expand-boolean-literals-transform.js +30 -53
  4. package/dist/transforms-by-id/expand-boolean-literals/get-inverted-binary-operator.d.ts +2 -0
  5. package/dist/transforms-by-id/expand-boolean-literals/get-inverted-binary-operator.js +11 -0
  6. package/dist/transforms-by-id/expand-boolean-literals/manifest.json +3 -3
  7. package/dist/transforms-by-id/expand-boolean-literals/try-expand-double-negated-membership-expression.d.ts +4 -0
  8. package/dist/transforms-by-id/expand-boolean-literals/try-expand-double-negated-membership-expression.js +16 -0
  9. package/dist/transforms-by-id/expand-boolean-literals/try-expand-double-negation-boolean-call.d.ts +10 -0
  10. package/dist/transforms-by-id/expand-boolean-literals/try-expand-double-negation-boolean-call.js +16 -0
  11. package/dist/transforms-by-id/expand-boolean-literals/try-expand-negated-binary-expression.d.ts +4 -0
  12. package/dist/transforms-by-id/expand-boolean-literals/try-expand-negated-binary-expression.js +34 -0
  13. package/dist/transforms-by-id/expand-boolean-literals/try-expand-negated-signed-numeric-literal.d.ts +4 -0
  14. package/dist/transforms-by-id/expand-boolean-literals/try-expand-negated-signed-numeric-literal.js +14 -0
  15. package/dist/transforms-by-id/expand-boolean-literals/try-expand-resolved-boolean-negation.d.ts +9 -0
  16. package/dist/transforms-by-id/expand-boolean-literals/try-expand-resolved-boolean-negation.js +14 -0
  17. package/dist/transforms-by-id/expand-boolean-literals/try-expand-resolved-double-negation.d.ts +9 -0
  18. package/dist/transforms-by-id/expand-boolean-literals/try-expand-resolved-double-negation.js +19 -0
  19. package/dist/transforms-by-id/rename-asap-wrappers/get-asap-wrapper-details.d.ts +1 -1
  20. package/dist/transforms-by-id/rename-asap-wrappers/get-asap-wrapper-details.js +45 -30
  21. package/dist/transforms-by-id/rename-asap-wrappers/get-forwarded-arguments-identifier.d.ts +2 -0
  22. package/dist/transforms-by-id/rename-asap-wrappers/get-forwarded-arguments-identifier.js +41 -0
  23. package/dist/transforms-by-id/rename-asap-wrappers/has-exactly-one-lexical-return-statement.d.ts +2 -0
  24. package/dist/transforms-by-id/rename-asap-wrappers/has-exactly-one-lexical-return-statement.js +48 -0
  25. package/dist/transforms-by-id/rename-asap-wrappers/manifest.json +3 -3
  26. package/dist/transforms-by-id/rename-asap-wrappers/rename-asap-wrappers-transform.js +23 -59
  27. package/dist/transforms-by-id/rename-awaiter-helper-functions/apply-awaiter-helper-renames.js +16 -7
  28. package/dist/transforms-by-id/rename-awaiter-helper-functions/manifest.json +4 -4
  29. package/dist/transforms-by-id/rename-awaiter-helper-functions/match-awaiter-helper-pattern.js +56 -19
  30. package/dist/transforms-by-id/rename-boolean-flag-variables/manifest.json +4 -4
  31. package/dist/transforms-by-id/rename-boolean-flag-variables/rename-boolean-flag-variables-transform.js +10 -9
  32. package/dist/transforms-by-id/rename-date-now-start-times/manifest.json +6 -6
  33. package/dist/transforms-by-id/rename-date-now-start-times/rename-date-now-start-times-transform.js +32 -4
  34. package/dist/transforms-by-id/rename-error-variables/add-error-like-parameter-rename.d.ts +9 -0
  35. package/dist/transforms-by-id/rename-error-variables/add-error-like-parameter-rename.js +90 -0
  36. package/dist/transforms-by-id/rename-error-variables/manifest.json +5 -5
  37. package/dist/transforms-by-id/rename-error-variables/match-error-constructor.js +40 -2
  38. package/dist/transforms-by-id/rename-error-variables/rename-error-variables-transform.js +40 -0
  39. package/dist/transforms-by-id/rename-event-parameters/event-parameter-usage.d.ts +1 -0
  40. package/dist/transforms-by-id/rename-event-parameters/event-parameter-usage.js +61 -8
  41. package/dist/transforms-by-id/rename-event-parameters/event-property-names.js +11 -2
  42. package/dist/transforms-by-id/rename-event-parameters/has-keyboard-literal-comparison-signal.d.ts +3 -0
  43. package/dist/transforms-by-id/rename-event-parameters/has-keyboard-literal-comparison-signal.js +77 -0
  44. package/dist/transforms-by-id/rename-event-parameters/manifest.json +4 -4
  45. package/dist/transforms-by-id/rename-execfile-arguments/detect-execfile-call.js +13 -13
  46. package/dist/transforms-by-id/rename-execfile-arguments/manifest.json +5 -5
  47. package/dist/transforms-by-id/rename-http-server-parameters/analyze-parameters.d.ts +1 -1
  48. package/dist/transforms-by-id/rename-http-server-parameters/analyze-parameters.js +5 -5
  49. package/dist/transforms-by-id/rename-http-server-parameters/detect-create-server-callee.js +30 -9
  50. package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-argument-path.js +26 -1
  51. package/dist/transforms-by-id/rename-http-server-parameters/handlers.js +3 -20
  52. package/dist/transforms-by-id/rename-http-server-parameters/has-property-usage.js +22 -0
  53. package/dist/transforms-by-id/rename-http-server-parameters/http-property-names.d.ts +2 -0
  54. package/dist/transforms-by-id/rename-http-server-parameters/http-property-names.js +38 -0
  55. package/dist/transforms-by-id/rename-http-server-parameters/manifest.json +3 -3
  56. package/dist/transforms-by-id/rename-http-server-parameters/rename-http-server-parameters-transform.js +3 -3
  57. package/dist/transforms-by-id/rename-http-server-parameters/validate-listener.d.ts +1 -1
  58. package/dist/transforms-by-id/rename-http-server-parameters/validate-listener.js +1 -3
  59. package/dist/transforms-by-id/rename-invalid-parameter-arguments/get-valid-base-name.d.ts +1 -0
  60. package/dist/transforms-by-id/rename-invalid-parameter-arguments/get-valid-base-name.js +51 -0
  61. package/dist/transforms-by-id/rename-invalid-parameter-arguments/manifest.json +4 -4
  62. package/dist/transforms-by-id/rename-invalid-parameter-arguments/rename-invalid-parameter-arguments-transform.js +3 -29
  63. package/dist/transforms-by-id/rename-object-keys-variables/is-safe-keys-reassignment.d.ts +1 -6
  64. package/dist/transforms-by-id/rename-object-keys-variables/is-safe-keys-reassignment.js +41 -80
  65. package/dist/transforms-by-id/rename-object-keys-variables/manifest.json +4 -4
  66. package/dist/transforms-by-id/rename-object-keys-variables/rename-object-keys-variables-transform.js +35 -11
  67. package/dist/transforms-by-id/rename-protobuf-encode-parameters/get-assigned-member-object-identifier-name.d.ts +3 -0
  68. package/dist/transforms-by-id/rename-protobuf-encode-parameters/get-assigned-member-object-identifier-name.js +12 -0
  69. package/dist/transforms-by-id/rename-protobuf-encode-parameters/get-assigned-member-property-name.js +24 -11
  70. package/dist/transforms-by-id/rename-protobuf-encode-parameters/get-two-identifier-parameter-names.js +1 -1
  71. package/dist/transforms-by-id/rename-protobuf-encode-parameters/has-protobuf-encode-body-signals.js +22 -7
  72. package/dist/transforms-by-id/rename-protobuf-encode-parameters/is-encode-delimited-function-candidate.d.ts +1 -1
  73. package/dist/transforms-by-id/rename-protobuf-encode-parameters/is-encode-delimited-function-candidate.js +22 -6
  74. package/dist/transforms-by-id/rename-protobuf-encode-parameters/manifest.json +3 -3
  75. package/dist/transforms-by-id/rename-protobuf-encode-parameters/rename-protobuf-encode-parameters-transform.js +2 -1
  76. package/dist/transforms-by-id/rename-sanitized-string-variables/manifest.json +3 -3
  77. package/dist/transforms-by-id/rename-sanitized-string-variables/rename-sanitized-string-variables-transform.js +33 -16
  78. package/dist/transforms-by-id/rename-stream-data-chunks/manifest.json +4 -4
  79. package/dist/transforms-by-id/rename-stream-data-chunks/rename-stream-data-chunks-transform.js +38 -50
  80. package/dist/transforms-by-id/rename-string-split-variables-v2/detect-split-result-candidate.js +41 -14
  81. package/dist/transforms-by-id/rename-string-split-variables-v2/has-array-like-split-usage.js +14 -1
  82. package/dist/transforms-by-id/rename-string-split-variables-v2/manifest.json +5 -5
  83. package/dist/transforms-by-id/rename-timeout-ids/collect-local-dynamic-lookup-scopes.d.ts +3 -0
  84. package/dist/transforms-by-id/rename-timeout-ids/collect-local-dynamic-lookup-scopes.js +41 -0
  85. package/dist/transforms-by-id/rename-timeout-ids/manifest.json +4 -4
  86. package/dist/transforms-by-id/rename-timeout-ids/rename-timeout-ids-transform.js +39 -31
  87. package/dist/transforms-by-id/rename-url-variables/manifest.json +4 -4
  88. package/dist/transforms-by-id/rename-url-variables/rename-url-variables-transform.js +66 -38
  89. package/dist/transforms-by-id/replace-dynamic-require-eval/manifest.json +5 -5
  90. package/dist/transforms-by-id/replace-dynamic-require-eval/replace-dynamic-require-eval-transform.js +31 -12
  91. package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/collect-deferred-variables.js +70 -57
  92. package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/manifest.json +5 -5
  93. package/dist/transforms-by-id/stabilize-deferred-top-level-bindings/stabilize-deferred-top-level-bindings-transform.js +17 -9
  94. package/dist/transforms-by-id/use-nullish-coalescing/extract-assignment-nullish-pattern.d.ts +10 -0
  95. package/dist/transforms-by-id/use-nullish-coalescing/extract-assignment-nullish-pattern.js +124 -0
  96. package/dist/transforms-by-id/use-nullish-coalescing/extract-identifier-nullish-pattern.d.ts +7 -0
  97. package/dist/transforms-by-id/use-nullish-coalescing/extract-identifier-nullish-pattern.js +99 -0
  98. package/dist/transforms-by-id/use-nullish-coalescing/extract-nullish-coalescing-pattern.d.ts +6 -16
  99. package/dist/transforms-by-id/use-nullish-coalescing/extract-nullish-coalescing-pattern.js +6 -80
  100. package/dist/transforms-by-id/use-nullish-coalescing/manifest.json +4 -4
  101. package/dist/transforms-by-id/use-nullish-coalescing/use-nullish-coalescing-transform.js +17 -3
  102. package/package.json +1 -1
@@ -60,8 +60,14 @@ export const computeDirectoryDiff = async (options) => {
60
60
  }
61
61
  if (!outputStream)
62
62
  continue;
63
- if (outputStreamError)
63
+ if (outputStreamError) {
64
+ if (outputPath &&
65
+ isErrnoException(outputStreamError) &&
66
+ outputStreamError.code === "EEXIST") {
67
+ throw new Error(`Refusing to overwrite existing diff output file: ${outputPath}. Re-run with --overwrite to replace.`);
68
+ }
64
69
  throw outputStreamError;
70
+ }
65
71
  if (outputStream.write(outputLine))
66
72
  continue;
67
73
  await once(outputStream, "drain");
@@ -71,9 +77,9 @@ export const computeDirectoryDiff = async (options) => {
71
77
  rl.close();
72
78
  }
73
79
  if (outputStreamError) {
74
- if (outputPath && isErrnoException(outputStreamError)) {
75
- if (outputStreamError.code !== "EEXIST")
76
- throw outputStreamError;
80
+ if (outputPath &&
81
+ isErrnoException(outputStreamError) &&
82
+ outputStreamError.code === "EEXIST") {
77
83
  throw new Error(`Refusing to overwrite existing diff output file: ${outputPath}. Re-run with --overwrite to replace.`);
78
84
  }
79
85
  throw outputStreamError;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "recommended": {
3
- "diffSizePercent": 26.01296443285331,
4
- "notes": "Measured with baseline none: 26.01% of original diff."
3
+ "diffSizePercent": 23.705446573685602,
4
+ "notes": "Measured with baseline none: 23.71% of original diff."
5
5
  }
6
6
  }
@@ -1,7 +1,12 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { getFilesToProcess, } from "../../core/types.js";
3
3
  import { hasGlobalBooleanRebinding } from "./detect-global-boolean-rebinding.js";
4
- import { resolveBooleanNegationValue, resolveDoubleNegationValue, } from "./resolve-literal-boolean-value.js";
4
+ import { tryExpandDoubleNegationBooleanCall } from "./try-expand-double-negation-boolean-call.js";
5
+ import { tryExpandDoubleNegatedMembershipExpression } from "./try-expand-double-negated-membership-expression.js";
6
+ import { tryExpandNegatedBinaryExpression } from "./try-expand-negated-binary-expression.js";
7
+ import { tryExpandNegatedSignedNumericLiteral } from "./try-expand-negated-signed-numeric-literal.js";
8
+ import { tryExpandResolvedBooleanNegation } from "./try-expand-resolved-boolean-negation.js";
9
+ import { tryExpandResolvedDoubleNegation } from "./try-expand-resolved-double-negation.js";
5
10
  const require = createRequire(import.meta.url);
6
11
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7
12
  const traverse = require("@babel/traverse").default;
@@ -20,73 +25,45 @@ export const expandBooleanLiteralsTransform = {
20
25
  UnaryExpression(path) {
21
26
  nodesVisited++;
22
27
  const { operator, argument } = path.node;
23
- if (operator !== "!") {
28
+ if (operator !== "!")
24
29
  return;
25
- }
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));
30
+ const isInsideWithStatement = path.findParent((parentPath) => parentPath.isWithStatement()) !==
31
+ null;
32
+ if (tryExpandResolvedBooleanNegation(path, {
33
+ isInsideWithStatement,
34
+ t,
35
+ })) {
36
36
  transformationsApplied++;
37
37
  return;
38
38
  }
39
- if (argument.type === "UnaryExpression" &&
40
- argument.operator === "!" &&
41
- argument.argument.type === "NumericLiteral") {
42
- const booleanValue = argument.argument.value !== 0;
43
- path.replaceWith(t.booleanLiteral(booleanValue));
39
+ if (tryExpandNegatedBinaryExpression(path, t)) {
44
40
  transformationsApplied++;
45
41
  return;
46
42
  }
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)));
43
+ if (tryExpandDoubleNegatedMembershipExpression(path, t)) {
50
44
  transformationsApplied++;
51
45
  return;
52
46
  }
53
- if (argument.type === "UnaryExpression" &&
54
- argument.operator === "!") {
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++;
63
- return;
64
- }
65
- }
66
- if (argument.type === "UnaryExpression" &&
67
- argument.operator === "!") {
68
- if (path.scope.hasBinding("Boolean", true)) {
69
- return;
70
- }
71
- if (hasGlobalBooleanRebindingInFile) {
72
- return;
73
- }
74
- path.replaceWith(t.callExpression(t.identifier("Boolean"), [
75
- t.cloneNode(argument.argument, true),
76
- ]));
47
+ if (tryExpandResolvedDoubleNegation(path, {
48
+ isInsideWithStatement,
49
+ t,
50
+ })) {
77
51
  transformationsApplied++;
78
52
  return;
79
53
  }
80
- if (argument.type === "UnaryExpression" &&
81
- (argument.operator === "+" || argument.operator === "-") &&
82
- argument.argument.type === "NumericLiteral") {
83
- const numericValue = argument.operator === "-"
84
- ? -argument.argument.value
85
- : argument.argument.value;
86
- const booleanValue = numericValue === 0;
87
- path.replaceWith(t.booleanLiteral(booleanValue));
54
+ if (tryExpandDoubleNegationBooleanCall(path, {
55
+ hasGlobalBooleanRebindingInFile,
56
+ isInsideWithStatement,
57
+ t,
58
+ })) {
88
59
  transformationsApplied++;
60
+ return;
89
61
  }
62
+ if (argument.type !== "UnaryExpression")
63
+ return;
64
+ if (!tryExpandNegatedSignedNumericLiteral(path, t))
65
+ return;
66
+ transformationsApplied++;
90
67
  },
91
68
  });
92
69
  }
@@ -0,0 +1,2 @@
1
+ import type { BinaryExpression } from "@babel/types";
2
+ export declare const getInvertedBinaryOperator: (operator: BinaryExpression["operator"]) => BinaryExpression["operator"] | undefined;
@@ -0,0 +1,11 @@
1
+ export const getInvertedBinaryOperator = (operator) => {
2
+ if (operator === "===")
3
+ return "!==";
4
+ if (operator === "!==")
5
+ return "===";
6
+ if (operator === "==")
7
+ return "!=";
8
+ if (operator === "!=")
9
+ return "==";
10
+ return undefined;
11
+ };
@@ -3,9 +3,9 @@
3
3
  "evaluations": {
4
4
  "claude-code-2.1.10:claude-code-2.1.11": {
5
5
  "diffSizePercent": 100,
6
- "evaluatedAt": "2026-02-10T20:27:40.370Z",
7
- "changedLines": 37534,
8
- "durationSeconds": 40.372261375,
6
+ "evaluatedAt": "2026-02-22T15:30:29.948Z",
7
+ "changedLines": 37562,
8
+ "durationSeconds": 41.198199708,
9
9
  "stableNames": 1357
10
10
  }
11
11
  },
@@ -0,0 +1,4 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type * as BabelTypes from "@babel/types";
3
+ import type { UnaryExpression } from "@babel/types";
4
+ export declare const tryExpandDoubleNegatedMembershipExpression: (path: NodePath<UnaryExpression>, t: typeof BabelTypes) => boolean;
@@ -0,0 +1,16 @@
1
+ const isMembershipOperator = (operator) => {
2
+ return operator === "in" || operator === "instanceof";
3
+ };
4
+ export const tryExpandDoubleNegatedMembershipExpression = (path, t) => {
5
+ const { argument } = path.node;
6
+ if (argument.type !== "UnaryExpression" || argument.operator !== "!") {
7
+ return false;
8
+ }
9
+ const innerArgument = argument.argument;
10
+ if (innerArgument.type !== "BinaryExpression")
11
+ return false;
12
+ if (!isMembershipOperator(innerArgument.operator))
13
+ return false;
14
+ path.replaceWith(t.binaryExpression("===", t.parenthesizedExpression(t.cloneNode(innerArgument, true)), t.booleanLiteral(true)));
15
+ return true;
16
+ };
@@ -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 TryExpandDoubleNegationBooleanCallContext = {
5
+ hasGlobalBooleanRebindingInFile: boolean;
6
+ isInsideWithStatement: boolean;
7
+ t: typeof BabelTypes;
8
+ };
9
+ export declare const tryExpandDoubleNegationBooleanCall: (path: NodePath<UnaryExpression>, context: TryExpandDoubleNegationBooleanCallContext) => boolean;
10
+ export {};
@@ -0,0 +1,16 @@
1
+ export const tryExpandDoubleNegationBooleanCall = (path, context) => {
2
+ const { argument } = path.node;
3
+ if (argument.type !== "UnaryExpression" || argument.operator !== "!") {
4
+ return false;
5
+ }
6
+ if (context.isInsideWithStatement)
7
+ return false;
8
+ if (path.scope.hasBinding("Boolean", true))
9
+ return false;
10
+ if (context.hasGlobalBooleanRebindingInFile)
11
+ return false;
12
+ path.replaceWith(context.t.callExpression(context.t.identifier("Boolean"), [
13
+ context.t.cloneNode(argument.argument, true),
14
+ ]));
15
+ return true;
16
+ };
@@ -0,0 +1,4 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type * as BabelTypes from "@babel/types";
3
+ import type { UnaryExpression } from "@babel/types";
4
+ export declare const tryExpandNegatedBinaryExpression: (path: NodePath<UnaryExpression>, t: typeof BabelTypes) => boolean;
@@ -0,0 +1,34 @@
1
+ import { getInvertedBinaryOperator } from "./get-inverted-binary-operator.js";
2
+ const isRelationalOperator = (operator) => {
3
+ return (operator === "<" ||
4
+ operator === "<=" ||
5
+ operator === ">" ||
6
+ operator === ">=");
7
+ };
8
+ const isMembershipOperator = (operator) => {
9
+ return operator === "in" || operator === "instanceof";
10
+ };
11
+ const replaceBinaryExpressionWithBooleanComparison = (path, t, value) => {
12
+ const binaryArgument = path.node.argument;
13
+ if (binaryArgument.type !== "BinaryExpression")
14
+ return;
15
+ path.replaceWith(t.binaryExpression("===", t.parenthesizedExpression(t.cloneNode(binaryArgument, true)), t.booleanLiteral(value)));
16
+ };
17
+ export const tryExpandNegatedBinaryExpression = (path, t) => {
18
+ const { argument } = path.node;
19
+ if (argument.type !== "BinaryExpression")
20
+ return false;
21
+ const invertedOperator = getInvertedBinaryOperator(argument.operator);
22
+ if (invertedOperator !== undefined) {
23
+ path.replaceWith(t.binaryExpression(invertedOperator, t.cloneNode(argument.left, true), t.cloneNode(argument.right, true)));
24
+ return true;
25
+ }
26
+ if (isRelationalOperator(argument.operator)) {
27
+ replaceBinaryExpressionWithBooleanComparison(path, t, false);
28
+ return true;
29
+ }
30
+ if (!isMembershipOperator(argument.operator))
31
+ return false;
32
+ replaceBinaryExpressionWithBooleanComparison(path, t, false);
33
+ return true;
34
+ };
@@ -0,0 +1,4 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type * as BabelTypes from "@babel/types";
3
+ import type { UnaryExpression } from "@babel/types";
4
+ export declare const tryExpandNegatedSignedNumericLiteral: (path: NodePath<UnaryExpression>, t: typeof BabelTypes) => boolean;
@@ -0,0 +1,14 @@
1
+ export const tryExpandNegatedSignedNumericLiteral = (path, t) => {
2
+ const { argument } = path.node;
3
+ if (argument.type !== "UnaryExpression")
4
+ return false;
5
+ if (argument.operator !== "+" && argument.operator !== "-")
6
+ return false;
7
+ if (argument.argument.type !== "NumericLiteral")
8
+ return false;
9
+ const numericValue = argument.operator === "-"
10
+ ? -argument.argument.value
11
+ : argument.argument.value;
12
+ path.replaceWith(t.booleanLiteral(numericValue === 0));
13
+ return true;
14
+ };
@@ -0,0 +1,9 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type * as BabelTypes from "@babel/types";
3
+ import type { UnaryExpression } from "@babel/types";
4
+ type TryExpandResolvedBooleanNegationContext = {
5
+ isInsideWithStatement: boolean;
6
+ t: typeof BabelTypes;
7
+ };
8
+ export declare const tryExpandResolvedBooleanNegation: (path: NodePath<UnaryExpression>, context: TryExpandResolvedBooleanNegationContext) => boolean;
9
+ export {};
@@ -0,0 +1,14 @@
1
+ import { resolveBooleanNegationValue } from "./resolve-literal-boolean-value.js";
2
+ export const tryExpandResolvedBooleanNegation = (path, context) => {
3
+ const resolution = resolveBooleanNegationValue(path, path.node.argument);
4
+ if (resolution === undefined)
5
+ return false;
6
+ if (context.isInsideWithStatement && resolution.kind !== "literal") {
7
+ return false;
8
+ }
9
+ if (resolution.kind === "literal" && !path.get("argument").isPure()) {
10
+ return false;
11
+ }
12
+ path.replaceWith(context.t.booleanLiteral(resolution.value));
13
+ return true;
14
+ };
@@ -0,0 +1,9 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type * as BabelTypes from "@babel/types";
3
+ import type { UnaryExpression } from "@babel/types";
4
+ type TryExpandResolvedDoubleNegationContext = {
5
+ isInsideWithStatement: boolean;
6
+ t: typeof BabelTypes;
7
+ };
8
+ export declare const tryExpandResolvedDoubleNegation: (path: NodePath<UnaryExpression>, context: TryExpandResolvedDoubleNegationContext) => boolean;
9
+ export {};
@@ -0,0 +1,19 @@
1
+ import { resolveDoubleNegationValue } from "./resolve-literal-boolean-value.js";
2
+ export const tryExpandResolvedDoubleNegation = (path, context) => {
3
+ const { argument } = path.node;
4
+ if (argument.type !== "UnaryExpression" || argument.operator !== "!") {
5
+ return false;
6
+ }
7
+ const resolution = resolveDoubleNegationValue(path, argument.argument);
8
+ if (resolution === undefined)
9
+ return false;
10
+ if (context.isInsideWithStatement && resolution.kind !== "literal") {
11
+ return false;
12
+ }
13
+ if (resolution.kind === "literal" &&
14
+ !path.get("argument.argument").isPure()) {
15
+ return false;
16
+ }
17
+ path.replaceWith(context.t.booleanLiteral(resolution.value));
18
+ return true;
19
+ };
@@ -1,5 +1,5 @@
1
1
  import type { ArrowFunctionExpression, FunctionExpression } from "@babel/types";
2
2
  export declare const getAsapWrapperDetails: (init: ArrowFunctionExpression | FunctionExpression) => {
3
3
  outerParameterName: string;
4
- innerParameterName: string;
4
+ innerParameterName: string | undefined;
5
5
  } | undefined;
@@ -1,12 +1,16 @@
1
+ import { getForwardedArgumentsIdentifier } from "./get-forwarded-arguments-identifier.js";
2
+ import { hasExactlyOneLexicalReturnStatement } from "./has-exactly-one-lexical-return-statement.js";
3
+ const SCHEDULER_METHOD_NAMES = new Set(["asap", "nextTick", "queueMicrotask"]);
1
4
  const isAsapCallee = (call) => {
2
5
  const callee = call.callee;
3
6
  if (callee.type === "Identifier") {
4
- return callee.name === "asap";
7
+ return SCHEDULER_METHOD_NAMES.has(callee.name);
5
8
  }
6
9
  if (callee.type === "MemberExpression") {
7
10
  if (callee.computed)
8
11
  return false;
9
- return (callee.property.type === "Identifier" && callee.property.name === "asap");
12
+ return (callee.property.type === "Identifier" &&
13
+ SCHEDULER_METHOD_NAMES.has(callee.property.name));
10
14
  }
11
15
  return false;
12
16
  };
@@ -19,10 +23,13 @@ const getIdentifierName = (node) => {
19
23
  return undefined;
20
24
  };
21
25
  const getReturnCallExpression = (block) => {
22
- if (block.body.length !== 1)
26
+ const returnStatements = block.body.filter((statement) => statement.type === "ReturnStatement");
27
+ if (returnStatements.length !== 1)
23
28
  return undefined;
24
- const statement = block.body[0];
25
- if (statement?.type !== "ReturnStatement")
29
+ if (!hasExactlyOneLexicalReturnStatement(block))
30
+ return undefined;
31
+ const statement = returnStatements.at(0);
32
+ if (!statement)
26
33
  return undefined;
27
34
  const argument = statement.argument;
28
35
  if (argument?.type !== "CallExpression")
@@ -38,10 +45,13 @@ const getFunctionCallExpression = (functionNode) => {
38
45
  return undefined;
39
46
  };
40
47
  const getReturnedFunctionExpression = (block) => {
41
- if (block.body.length !== 1)
48
+ const returnStatements = block.body.filter((statement) => statement.type === "ReturnStatement");
49
+ if (returnStatements.length !== 1)
50
+ return undefined;
51
+ if (!hasExactlyOneLexicalReturnStatement(block))
42
52
  return undefined;
43
- const statement = block.body[0];
44
- if (statement?.type !== "ReturnStatement")
53
+ const statement = returnStatements.at(0);
54
+ if (!statement)
45
55
  return undefined;
46
56
  const argument = statement.argument;
47
57
  if (argument?.type !== "ArrowFunctionExpression" &&
@@ -60,6 +70,16 @@ const getInnerWrapperFunction = (init) => {
60
70
  }
61
71
  return getReturnedFunctionExpression(init.body);
62
72
  };
73
+ const getInnerParameterName = (inner) => {
74
+ if (inner.params.length === 0)
75
+ return undefined;
76
+ if (inner.params.length !== 1)
77
+ return undefined;
78
+ const innerParameter = inner.params[0];
79
+ if (!innerParameter)
80
+ return undefined;
81
+ return getIdentifierName(innerParameter);
82
+ };
63
83
  export const getAsapWrapperDetails = (init) => {
64
84
  if (init.params.length !== 1)
65
85
  return undefined;
@@ -69,13 +89,8 @@ export const getAsapWrapperDetails = (init) => {
69
89
  const inner = getInnerWrapperFunction(init);
70
90
  if (!inner)
71
91
  return undefined;
72
- if (inner.params.length !== 1)
73
- return undefined;
74
- const innerParameter = inner.params[0];
75
- if (!innerParameter)
76
- return undefined;
77
- const restParameterName = getIdentifierName(innerParameter);
78
- if (!restParameterName)
92
+ const innerParameterName = getInnerParameterName(inner);
93
+ if (inner.params.length > 0 && !innerParameterName)
79
94
  return undefined;
80
95
  const innerCallExpression = getFunctionCallExpression(inner);
81
96
  if (!innerCallExpression)
@@ -94,23 +109,23 @@ export const getAsapWrapperDetails = (init) => {
94
109
  const callbackCallExpression = getFunctionCallExpression(callback);
95
110
  if (!callbackCallExpression)
96
111
  return undefined;
97
- const calledFunction = callbackCallExpression.callee;
98
- if (calledFunction.type !== "Identifier")
99
- return undefined;
100
- if (calledFunction.name !== outerParameter.name)
101
- return undefined;
102
- const callbackArguments = callbackCallExpression.arguments;
103
- if (callbackArguments.length !== 1)
104
- return undefined;
105
- const spread = callbackArguments[0];
106
- if (spread?.type !== "SpreadElement")
107
- return undefined;
108
- if (spread.argument.type !== "Identifier")
109
- return undefined;
110
- if (spread.argument.name !== restParameterName)
112
+ const forwardedArgumentsName = getForwardedArgumentsIdentifier(callbackCallExpression, outerParameter.name);
113
+ if (!forwardedArgumentsName)
111
114
  return undefined;
115
+ if (innerParameterName) {
116
+ if (forwardedArgumentsName !== innerParameterName)
117
+ return undefined;
118
+ }
119
+ else {
120
+ if (forwardedArgumentsName !== "arguments")
121
+ return undefined;
122
+ if (callback.type !== "ArrowFunctionExpression")
123
+ return undefined;
124
+ if (inner.type !== "FunctionExpression")
125
+ return undefined;
126
+ }
112
127
  return {
113
128
  outerParameterName: outerParameter.name,
114
- innerParameterName: restParameterName,
129
+ innerParameterName,
115
130
  };
116
131
  };
@@ -0,0 +1,2 @@
1
+ import type { CallExpression } from "@babel/types";
2
+ export declare const getForwardedArgumentsIdentifier: (callbackCallExpression: CallExpression, outerParameterName: string) => string | undefined;
@@ -0,0 +1,41 @@
1
+ export const getForwardedArgumentsIdentifier = (callbackCallExpression, outerParameterName) => {
2
+ const callee = callbackCallExpression.callee;
3
+ if (callee.type === "Identifier") {
4
+ if (callee.name !== outerParameterName)
5
+ return undefined;
6
+ if (callbackCallExpression.arguments.length !== 1)
7
+ return undefined;
8
+ const spreadArgument = callbackCallExpression.arguments[0];
9
+ if (spreadArgument?.type !== "SpreadElement")
10
+ return undefined;
11
+ if (spreadArgument.argument.type !== "Identifier")
12
+ return undefined;
13
+ return spreadArgument.argument.name;
14
+ }
15
+ if (callee.type !== "MemberExpression" ||
16
+ callee.computed ||
17
+ callee.object.type !== "Identifier" ||
18
+ callee.object.name !== outerParameterName ||
19
+ callee.property.type !== "Identifier") {
20
+ return undefined;
21
+ }
22
+ if (callee.property.name === "apply") {
23
+ if (callbackCallExpression.arguments.length !== 2)
24
+ return undefined;
25
+ const spreadArgument = callbackCallExpression.arguments[1];
26
+ if (spreadArgument?.type !== "Identifier")
27
+ return undefined;
28
+ return spreadArgument.name;
29
+ }
30
+ if (callee.property.name === "call") {
31
+ if (callbackCallExpression.arguments.length !== 2)
32
+ return undefined;
33
+ const spreadArgument = callbackCallExpression.arguments[1];
34
+ if (spreadArgument?.type !== "SpreadElement")
35
+ return undefined;
36
+ if (spreadArgument.argument.type !== "Identifier")
37
+ return undefined;
38
+ return spreadArgument.argument.name;
39
+ }
40
+ return undefined;
41
+ };
@@ -0,0 +1,2 @@
1
+ import type { BlockStatement } from "@babel/types";
2
+ export declare const hasExactlyOneLexicalReturnStatement: (block: BlockStatement) => boolean;
@@ -0,0 +1,48 @@
1
+ import { VISITOR_KEYS } from "@babel/types";
2
+ const FUNCTION_NODE_TYPES = new Set([
3
+ "ArrowFunctionExpression",
4
+ "ClassMethod",
5
+ "ClassPrivateMethod",
6
+ "FunctionDeclaration",
7
+ "FunctionExpression",
8
+ "ObjectMethod",
9
+ ]);
10
+ const isNode = (value) => Boolean(value &&
11
+ typeof value === "object" &&
12
+ "type" in value &&
13
+ typeof value.type === "string");
14
+ export const hasExactlyOneLexicalReturnStatement = (block) => {
15
+ let returnStatementCount = 0;
16
+ const stack = [...block.body];
17
+ while (stack.length > 0) {
18
+ const node = stack.pop();
19
+ if (!node)
20
+ continue;
21
+ if (node.type === "ReturnStatement") {
22
+ returnStatementCount += 1;
23
+ if (returnStatementCount > 1)
24
+ return false;
25
+ continue;
26
+ }
27
+ if (FUNCTION_NODE_TYPES.has(node.type))
28
+ continue;
29
+ const visitorKeys = VISITOR_KEYS[node.type];
30
+ if (!visitorKeys)
31
+ continue;
32
+ for (const key of visitorKeys) {
33
+ const child = node[key];
34
+ if (Array.isArray(child)) {
35
+ for (const nestedChild of child) {
36
+ if (isNode(nestedChild)) {
37
+ stack.push(nestedChild);
38
+ }
39
+ }
40
+ continue;
41
+ }
42
+ if (isNode(child)) {
43
+ stack.push(child);
44
+ }
45
+ }
46
+ }
47
+ return returnStatementCount === 1;
48
+ };
@@ -2,10 +2,10 @@
2
2
  "notes": "Measured with baseline none: 0.00%. Added to recommended for readability.",
3
3
  "evaluations": {
4
4
  "claude-code-2.1.10:claude-code-2.1.11": {
5
- "diffSizePercent": 100,
6
- "evaluatedAt": "2026-02-10T06:12:05.881Z",
5
+ "diffSizePercent": 99.99811014098348,
6
+ "evaluatedAt": "2026-02-22T15:48:34.214Z",
7
7
  "changedLines": 10,
8
- "durationSeconds": 69.52347904199999,
8
+ "durationSeconds": 31.124323875,
9
9
  "stableNames": 1358
10
10
  }
11
11
  },