miniread 1.121.1 → 1.121.2
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/presets/recommended/manifest.json +2 -2
- package/dist/transforms/shared/default-options-parameter-names/collect-default-options-parameter-names.js +68 -12
- package/dist/transforms/shared/default-options-parameter-names/get-defaulted-parameter-name.js +27 -0
- package/dist/transforms-by-id/rename-arguments-length-flags/has-shadowed-arguments-binding.js +5 -2
- package/dist/transforms-by-id/rename-arguments-length-flags/manifest.json +4 -4
- package/dist/transforms-by-id/rename-arguments-length-flags/rename-arguments-length-flags-transform.js +97 -4
- package/dist/transforms-by-id/rename-asap-wrappers/get-asap-wrapper-details.d.ts +2 -2
- package/dist/transforms-by-id/rename-asap-wrappers/get-asap-wrapper-details.js +32 -27
- package/dist/transforms-by-id/rename-asap-wrappers/get-direct-scheduled-callback-name.d.ts +2 -0
- package/dist/transforms-by-id/rename-asap-wrappers/get-direct-scheduled-callback-name.js +62 -0
- package/dist/transforms-by-id/rename-asap-wrappers/get-forwarded-arguments-identifier.js +19 -19
- package/dist/transforms-by-id/rename-asap-wrappers/is-asap-callee.d.ts +2 -0
- package/dist/transforms-by-id/rename-asap-wrappers/is-asap-callee.js +26 -0
- package/dist/transforms-by-id/rename-asap-wrappers/manifest.json +4 -4
- package/dist/transforms-by-id/rename-asap-wrappers/rename-asap-wrappers-transform.js +45 -26
- package/dist/transforms-by-id/rename-awaiter-parameters/awaiter-pattern.d.ts +3 -2
- package/dist/transforms-by-id/rename-awaiter-parameters/awaiter-pattern.js +1 -1
- package/dist/transforms-by-id/rename-awaiter-parameters/manifest.json +3 -3
- package/dist/transforms-by-id/rename-awaiter-parameters/rename-awaiter-bindings.d.ts +1 -1
- package/dist/transforms-by-id/rename-awaiter-parameters/rename-awaiter-bindings.js +47 -40
- package/dist/transforms-by-id/rename-default-options-parameters-v3/manifest.json +4 -4
- package/dist/transforms-by-id/rename-default-options-parameters-v3/rename-default-options-parameters-v3-transform.js +1 -4
- package/dist/transforms-by-id/rename-http-server-parameters/analyze-parameters.d.ts +4 -1
- package/dist/transforms-by-id/rename-http-server-parameters/analyze-parameters.js +6 -5
- package/dist/transforms-by-id/rename-http-server-parameters/detector.js +33 -6
- package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-argument-path.js +31 -4
- package/dist/transforms-by-id/rename-http-server-parameters/get-listener-from-request-event-registration.js +14 -3
- package/dist/transforms-by-id/rename-http-server-parameters/handlers.d.ts +1 -1
- package/dist/transforms-by-id/rename-http-server-parameters/handlers.js +26 -12
- package/dist/transforms-by-id/rename-http-server-parameters/manifest.json +3 -3
- package/dist/transforms-by-id/rename-http-server-parameters/rename-http-server-parameters-transform.js +4 -4
- package/dist/transforms-by-id/rename-http-server-parameters/validate-listener.js +16 -6
- package/dist/transforms-by-id/rename-indexeddb-request-variables/analyze-indexeddb-request-binding.d.ts +2 -1
- package/dist/transforms-by-id/rename-indexeddb-request-variables/analyze-indexeddb-request-binding.js +57 -0
- package/dist/transforms-by-id/rename-indexeddb-request-variables/collect-local-dynamic-lookup-scopes.d.ts +3 -0
- package/dist/transforms-by-id/rename-indexeddb-request-variables/collect-local-dynamic-lookup-scopes.js +29 -0
- package/dist/transforms-by-id/rename-indexeddb-request-variables/manifest.json +3 -3
- package/dist/transforms-by-id/rename-indexeddb-request-variables/rename-indexeddb-request-variables-transform.js +32 -16
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/get-member-expression-object-parameter-binding.d.ts +3 -0
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/get-member-expression-object-parameter-binding.js +16 -0
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/get-name-argument-value.d.ts +3 -0
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/get-name-argument-value.js +16 -0
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/is-invalid-parameter-error-call.d.ts +3 -0
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/is-invalid-parameter-error-call.js +37 -0
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/manifest.json +4 -4
- package/dist/transforms-by-id/rename-invalid-parameter-arguments/rename-invalid-parameter-arguments-transform.js +36 -19
- package/dist/transforms-by-id/rename-object-entries-parameters/is-object-entries-consumer-call.js +44 -17
- package/dist/transforms-by-id/rename-object-entries-parameters/manifest.json +3 -3
- package/dist/transforms-by-id/rename-object-entries-parameters/rename-object-entries-parameters-transform.js +13 -14
- package/dist/transforms-by-id/replace-dynamic-require-eval/is-eval-require-callee.d.ts +3 -0
- package/dist/transforms-by-id/replace-dynamic-require-eval/is-eval-require-callee.js +42 -0
- package/dist/transforms-by-id/replace-dynamic-require-eval/is-obfuscated-require-eval-call-argument.d.ts +6 -0
- package/dist/transforms-by-id/replace-dynamic-require-eval/is-obfuscated-require-eval-call-argument.js +49 -0
- package/dist/transforms-by-id/replace-dynamic-require-eval/manifest.json +2 -2
- package/dist/transforms-by-id/replace-dynamic-require-eval/replace-dynamic-require-eval-transform.js +6 -26
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/check-rhs-stability.d.ts +1 -1
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/check-rhs-stability.js +6 -2
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/get-rhs-code-for-stable-hash.d.ts +2 -0
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/get-rhs-code-for-stable-hash.js +33 -0
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/get-single-assigned-identifier-name.d.ts +3 -0
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/get-single-assigned-identifier-name.js +63 -0
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/has-name-independent-shadowing-risk.d.ts +2 -0
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/has-name-independent-shadowing-risk.js +17 -0
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/manifest.json +5 -5
- package/dist/transforms-by-id/stabilize-deferred-stable-rhs/stabilize-deferred-stable-rhs-transform.js +16 -25
- package/dist/transforms-by-id/stabilize-top-level-bindings/collect-first-program-scope-assignments.js +20 -1
- package/dist/transforms-by-id/stabilize-top-level-bindings/has-disallowed-function-class-assignment-reference.d.ts +2 -3
- package/dist/transforms-by-id/stabilize-top-level-bindings/has-disallowed-function-class-assignment-reference.js +43 -54
- package/dist/transforms-by-id/stabilize-top-level-bindings/manifest.json +6 -6
- package/package.json +1 -1
|
@@ -25,6 +25,56 @@ const getDefaultOptionsParameterNamesFromChain = (statement, parameterNames, all
|
|
|
25
25
|
}
|
|
26
26
|
return matchedParameterName;
|
|
27
27
|
};
|
|
28
|
+
const isEmptyObjectLiteral = (expression) => {
|
|
29
|
+
if (!t.isObjectExpression(expression))
|
|
30
|
+
return false;
|
|
31
|
+
return expression.properties.length === 0;
|
|
32
|
+
};
|
|
33
|
+
const getExpressionStatementDefaultedParameterName = (statement, parameterNames) => {
|
|
34
|
+
if (!t.isExpressionStatement(statement))
|
|
35
|
+
return undefined;
|
|
36
|
+
const { expression } = statement;
|
|
37
|
+
if (t.isAssignmentExpression(expression) &&
|
|
38
|
+
(expression.operator === "||=" || expression.operator === "??=")) {
|
|
39
|
+
if (!t.isIdentifier(expression.left))
|
|
40
|
+
return undefined;
|
|
41
|
+
if (!parameterNames.has(expression.left.name))
|
|
42
|
+
return undefined;
|
|
43
|
+
if (!isEmptyObjectLiteral(expression.right))
|
|
44
|
+
return undefined;
|
|
45
|
+
return expression.left.name;
|
|
46
|
+
}
|
|
47
|
+
if (t.isAssignmentExpression(expression) &&
|
|
48
|
+
expression.operator === "=" &&
|
|
49
|
+
t.isIdentifier(expression.left) &&
|
|
50
|
+
t.isLogicalExpression(expression.right) &&
|
|
51
|
+
(expression.right.operator === "||" || expression.right.operator === "??")) {
|
|
52
|
+
const { left, right } = expression.right;
|
|
53
|
+
if (!t.isIdentifier(left, { name: expression.left.name }))
|
|
54
|
+
return undefined;
|
|
55
|
+
if (!parameterNames.has(expression.left.name))
|
|
56
|
+
return undefined;
|
|
57
|
+
if (!isEmptyObjectLiteral(right))
|
|
58
|
+
return undefined;
|
|
59
|
+
return expression.left.name;
|
|
60
|
+
}
|
|
61
|
+
if (t.isLogicalExpression(expression) &&
|
|
62
|
+
(expression.operator === "||" || expression.operator === "??")) {
|
|
63
|
+
if (!t.isIdentifier(expression.left))
|
|
64
|
+
return undefined;
|
|
65
|
+
if (!parameterNames.has(expression.left.name))
|
|
66
|
+
return undefined;
|
|
67
|
+
const right = expression.right;
|
|
68
|
+
if (!t.isAssignmentExpression(right, { operator: "=" }))
|
|
69
|
+
return undefined;
|
|
70
|
+
if (!t.isIdentifier(right.left, { name: expression.left.name }))
|
|
71
|
+
return undefined;
|
|
72
|
+
if (!isEmptyObjectLiteral(right.right))
|
|
73
|
+
return undefined;
|
|
74
|
+
return expression.left.name;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
};
|
|
28
78
|
export const collectDefaultOptionsParameterNames = (path) => {
|
|
29
79
|
// Intentionally includes parent scopes, so an outer `function(undefined){...}`
|
|
30
80
|
// disables identifier-based undefined checks for nested functions too.
|
|
@@ -42,13 +92,24 @@ export const collectDefaultOptionsParameterNames = (path) => {
|
|
|
42
92
|
parameterNames.add(parameter.left.name);
|
|
43
93
|
}
|
|
44
94
|
}
|
|
45
|
-
let
|
|
46
|
-
|
|
95
|
+
let sawDefaultingStatement = false;
|
|
96
|
+
const matchedParameterNames = new Set();
|
|
47
97
|
for (const statement of body.body) {
|
|
48
98
|
if (t.isExpressionStatement(statement) &&
|
|
49
99
|
t.isStringLiteral(statement.expression)) {
|
|
50
100
|
continue;
|
|
51
101
|
}
|
|
102
|
+
if (!sawDefaultingStatement &&
|
|
103
|
+
t.isVariableDeclaration(statement) &&
|
|
104
|
+
statement.declarations.every((declarator) => t.isIdentifier(declarator.id) && declarator.init === null)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const expressionStatementMatch = getExpressionStatementDefaultedParameterName(statement, parameterNames);
|
|
108
|
+
if (expressionStatementMatch) {
|
|
109
|
+
sawDefaultingStatement = true;
|
|
110
|
+
matchedParameterNames.add(expressionStatementMatch);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
52
113
|
// Intentionally only match chains at the top of the function body.
|
|
53
114
|
// This keeps matches deterministic and avoids deeper control-flow guesses.
|
|
54
115
|
if (!t.isIfStatement(statement))
|
|
@@ -56,17 +117,12 @@ export const collectDefaultOptionsParameterNames = (path) => {
|
|
|
56
117
|
const chainMatch = getDefaultOptionsParameterNamesFromChain(statement, parameterNames, allowUndefinedCheck);
|
|
57
118
|
if (!chainMatch)
|
|
58
119
|
break;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
matchedParameterName = chainMatch;
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (matchedParameterName !== chainMatch)
|
|
65
|
-
return [];
|
|
120
|
+
sawDefaultingStatement = true;
|
|
121
|
+
matchedParameterNames.add(chainMatch);
|
|
66
122
|
}
|
|
67
|
-
if (!
|
|
123
|
+
if (!sawDefaultingStatement)
|
|
68
124
|
return [];
|
|
69
|
-
if (
|
|
125
|
+
if (matchedParameterNames.size === 0)
|
|
70
126
|
return [];
|
|
71
|
-
return [
|
|
127
|
+
return [...matchedParameterNames];
|
|
72
128
|
};
|
package/dist/transforms/shared/default-options-parameter-names/get-defaulted-parameter-name.js
CHANGED
|
@@ -30,6 +30,24 @@ const getVoidZeroCheckedParameterName = (test) => {
|
|
|
30
30
|
}
|
|
31
31
|
return undefined;
|
|
32
32
|
};
|
|
33
|
+
const getNullishCheckedParameterName = (test) => {
|
|
34
|
+
if (!t.isBinaryExpression(test, { operator: "==" }))
|
|
35
|
+
return undefined;
|
|
36
|
+
const { left, right } = test;
|
|
37
|
+
if (t.isIdentifier(left) && t.isNullLiteral(right)) {
|
|
38
|
+
return left.name;
|
|
39
|
+
}
|
|
40
|
+
if (t.isNullLiteral(left) && t.isIdentifier(right)) {
|
|
41
|
+
return right.name;
|
|
42
|
+
}
|
|
43
|
+
if (t.isIdentifier(left) && isCanonicalUndefinedLiteral(right)) {
|
|
44
|
+
return left.name;
|
|
45
|
+
}
|
|
46
|
+
if (isCanonicalUndefinedLiteral(left) && t.isIdentifier(right)) {
|
|
47
|
+
return right.name;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
};
|
|
33
51
|
const getFalsyCheckedParameterName = (test) => {
|
|
34
52
|
if (!t.isUnaryExpression(test, { operator: "!" }))
|
|
35
53
|
return undefined;
|
|
@@ -95,6 +113,15 @@ export const getDefaultedParameterName = (statement, parameterNames, options) =>
|
|
|
95
113
|
}
|
|
96
114
|
return voidZeroCheckedName;
|
|
97
115
|
}
|
|
116
|
+
const nullishCheckedName = getNullishCheckedParameterName(statement.test);
|
|
117
|
+
if (nullishCheckedName) {
|
|
118
|
+
if (!parameterNames.has(nullishCheckedName))
|
|
119
|
+
return undefined;
|
|
120
|
+
if (!hasEmptyObjectAssignment(statement.consequent, nullishCheckedName)) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return nullishCheckedName;
|
|
124
|
+
}
|
|
98
125
|
const falsyCheckedName = getFalsyCheckedParameterName(statement.test);
|
|
99
126
|
if (falsyCheckedName) {
|
|
100
127
|
if (!parameterNames.has(falsyCheckedName))
|
package/dist/transforms-by-id/rename-arguments-length-flags/has-shadowed-arguments-binding.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export const hasShadowedArgumentsBinding = (path) => {
|
|
2
2
|
const functionScope = path.scope.getFunctionParent();
|
|
3
|
-
if (!functionScope)
|
|
4
|
-
return false;
|
|
5
3
|
const argumentsBinding = path.scope.getBinding("arguments");
|
|
4
|
+
if (!functionScope) {
|
|
5
|
+
if (!argumentsBinding)
|
|
6
|
+
return false;
|
|
7
|
+
return argumentsBinding.scope.path.isProgram();
|
|
8
|
+
}
|
|
6
9
|
if (!argumentsBinding)
|
|
7
10
|
return false;
|
|
8
11
|
if (functionScope.path.isArrowFunctionExpression()) {
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
"evaluations": {
|
|
4
4
|
"claude-code-2.1.10:claude-code-2.1.11": {
|
|
5
5
|
"diffSizePercent": 100,
|
|
6
|
-
"evaluatedAt": "2026-02-
|
|
7
|
-
"changedLines":
|
|
8
|
-
"durationSeconds":
|
|
9
|
-
"stableNames":
|
|
6
|
+
"evaluatedAt": "2026-02-28T11:36:51.668Z",
|
|
7
|
+
"changedLines": 258,
|
|
8
|
+
"durationSeconds": 102.80917774999999,
|
|
9
|
+
"stableNames": 1363
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"recommended": true,
|
|
@@ -1,12 +1,76 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { VISITOR_KEYS, isNode, isPrivateName, isFunction, } from "@babel/types";
|
|
2
3
|
import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
|
|
3
4
|
import { getFilesToProcess, } from "../../core/types.js";
|
|
4
5
|
import { getArgumentsLengthBaseName } from "./get-arguments-length-base-name.js";
|
|
5
6
|
import { getArgumentsLengthMatch } from "./get-arguments-length-match.js";
|
|
6
7
|
import { hasShadowedArgumentsBinding } from "./has-shadowed-arguments-binding.js";
|
|
8
|
+
import { getExpression, isArgumentsLengthExpression, } from "./arguments-length-expression.js";
|
|
7
9
|
const require = createRequire(import.meta.url);
|
|
8
10
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
9
11
|
const traverse = require("@babel/traverse").default;
|
|
12
|
+
const getArgumentsLengthOffsetBaseName = (init) => {
|
|
13
|
+
const left = getExpression(init.left);
|
|
14
|
+
const right = getExpression(init.right);
|
|
15
|
+
if (!left || !right)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (!isArgumentsLengthExpression(left))
|
|
18
|
+
return undefined;
|
|
19
|
+
if (right.type !== "NumericLiteral")
|
|
20
|
+
return undefined;
|
|
21
|
+
if (!Number.isInteger(right.value))
|
|
22
|
+
return undefined;
|
|
23
|
+
if (init.operator === "-") {
|
|
24
|
+
if (right.value < 1)
|
|
25
|
+
return undefined;
|
|
26
|
+
return `argCountMinus${right.value}`;
|
|
27
|
+
}
|
|
28
|
+
if (init.operator === "+") {
|
|
29
|
+
if (right.value < 1)
|
|
30
|
+
return undefined;
|
|
31
|
+
return `argCountPlus${right.value}`;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
};
|
|
35
|
+
const hasArgumentsLengthReference = (expression) => {
|
|
36
|
+
const stack = [expression];
|
|
37
|
+
while (stack.length > 0) {
|
|
38
|
+
const current = stack.pop();
|
|
39
|
+
if (!current)
|
|
40
|
+
continue;
|
|
41
|
+
if (isArgumentsLengthExpression(current))
|
|
42
|
+
return true;
|
|
43
|
+
if (isFunction(current))
|
|
44
|
+
continue;
|
|
45
|
+
const visitorKeys = VISITOR_KEYS[current.type];
|
|
46
|
+
if (!visitorKeys)
|
|
47
|
+
continue;
|
|
48
|
+
for (const key of visitorKeys) {
|
|
49
|
+
const value = current[key];
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
for (const child of value) {
|
|
52
|
+
if (!isNode(child))
|
|
53
|
+
continue;
|
|
54
|
+
if (!isExpression(child))
|
|
55
|
+
continue;
|
|
56
|
+
stack.push(child);
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!isNode(value) || isPrivateName(value))
|
|
61
|
+
continue;
|
|
62
|
+
if (!isExpression(value))
|
|
63
|
+
continue;
|
|
64
|
+
stack.push(value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
};
|
|
69
|
+
const isExpression = (value) => {
|
|
70
|
+
if (!isNode(value))
|
|
71
|
+
return false;
|
|
72
|
+
return !isPrivateName(value);
|
|
73
|
+
};
|
|
10
74
|
export const renameArgumentsLengthFlagsTransform = {
|
|
11
75
|
id: "rename-arguments-length-flags",
|
|
12
76
|
description: "Rename arguments.length guards (>= N, < N) to $hasAtLeastNArgs/$hasFewerThanNArgs when stable",
|
|
@@ -28,18 +92,47 @@ export const renameArgumentsLengthFlagsTransform = {
|
|
|
28
92
|
const init = path.node.init;
|
|
29
93
|
if (!init)
|
|
30
94
|
return;
|
|
31
|
-
if (
|
|
95
|
+
if (!isExpression(init))
|
|
32
96
|
return;
|
|
33
|
-
|
|
34
|
-
if (!match || match.condition.count < 1)
|
|
97
|
+
if (hasShadowedArgumentsBinding(path))
|
|
35
98
|
return;
|
|
36
99
|
const binding = path.scope.getBinding(id.name);
|
|
37
100
|
if (!binding?.constant)
|
|
38
101
|
return;
|
|
102
|
+
if (isArgumentsLengthExpression(init)) {
|
|
103
|
+
renameGroup.add({
|
|
104
|
+
scope: binding.scope,
|
|
105
|
+
currentName: id.name,
|
|
106
|
+
baseName: "argCount",
|
|
107
|
+
});
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (init.type === "BinaryExpression") {
|
|
111
|
+
const offsetBaseName = getArgumentsLengthOffsetBaseName(init);
|
|
112
|
+
if (offsetBaseName) {
|
|
113
|
+
renameGroup.add({
|
|
114
|
+
scope: binding.scope,
|
|
115
|
+
currentName: id.name,
|
|
116
|
+
baseName: offsetBaseName,
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const match = getArgumentsLengthMatch(init);
|
|
122
|
+
if (match && match.condition.count >= 1) {
|
|
123
|
+
renameGroup.add({
|
|
124
|
+
scope: binding.scope,
|
|
125
|
+
currentName: id.name,
|
|
126
|
+
baseName: getArgumentsLengthBaseName(match),
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (!hasArgumentsLengthReference(init))
|
|
131
|
+
return;
|
|
39
132
|
renameGroup.add({
|
|
40
133
|
scope: binding.scope,
|
|
41
134
|
currentName: id.name,
|
|
42
|
-
baseName:
|
|
135
|
+
baseName: "argLengthValue",
|
|
43
136
|
});
|
|
44
137
|
},
|
|
45
138
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ArrowFunctionExpression, FunctionExpression } from "@babel/types";
|
|
2
|
-
export declare const getAsapWrapperDetails: (init: ArrowFunctionExpression | FunctionExpression) => {
|
|
1
|
+
import type { ArrowFunctionExpression, FunctionDeclaration, FunctionExpression } from "@babel/types";
|
|
2
|
+
export declare const getAsapWrapperDetails: (init: ArrowFunctionExpression | FunctionExpression | FunctionDeclaration) => {
|
|
3
3
|
outerParameterName: string;
|
|
4
4
|
innerParameterName: string | undefined;
|
|
5
5
|
} | undefined;
|
|
@@ -1,19 +1,7 @@
|
|
|
1
|
+
import { getDirectScheduledCallbackName } from "./get-direct-scheduled-callback-name.js";
|
|
1
2
|
import { getForwardedArgumentsIdentifier } from "./get-forwarded-arguments-identifier.js";
|
|
2
3
|
import { hasExactlyOneLexicalReturnStatement } from "./has-exactly-one-lexical-return-statement.js";
|
|
3
|
-
|
|
4
|
-
const isAsapCallee = (call) => {
|
|
5
|
-
const callee = call.callee;
|
|
6
|
-
if (callee.type === "Identifier") {
|
|
7
|
-
return SCHEDULER_METHOD_NAMES.has(callee.name);
|
|
8
|
-
}
|
|
9
|
-
if (callee.type === "MemberExpression") {
|
|
10
|
-
if (callee.computed)
|
|
11
|
-
return false;
|
|
12
|
-
return (callee.property.type === "Identifier" &&
|
|
13
|
-
SCHEDULER_METHOD_NAMES.has(callee.property.name));
|
|
14
|
-
}
|
|
15
|
-
return false;
|
|
16
|
-
};
|
|
4
|
+
import { isAsapCallee } from "./is-asap-callee.js";
|
|
17
5
|
const getIdentifierName = (node) => {
|
|
18
6
|
if (node.type === "Identifier")
|
|
19
7
|
return node.name;
|
|
@@ -81,11 +69,22 @@ const getInnerParameterName = (inner) => {
|
|
|
81
69
|
return getIdentifierName(innerParameter);
|
|
82
70
|
};
|
|
83
71
|
export const getAsapWrapperDetails = (init) => {
|
|
84
|
-
if (init.params.length
|
|
72
|
+
if (init.params.length === 0)
|
|
85
73
|
return undefined;
|
|
86
74
|
const outerParameter = init.params[0];
|
|
87
75
|
if (outerParameter?.type !== "Identifier")
|
|
88
76
|
return undefined;
|
|
77
|
+
if (init.body.type === "BlockStatement") {
|
|
78
|
+
const directScheduledCallbackName = getDirectScheduledCallbackName(init.body);
|
|
79
|
+
if (directScheduledCallbackName) {
|
|
80
|
+
if (directScheduledCallbackName !== outerParameter.name)
|
|
81
|
+
return undefined;
|
|
82
|
+
return {
|
|
83
|
+
outerParameterName: outerParameter.name,
|
|
84
|
+
innerParameterName: undefined,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
89
88
|
const inner = getInnerWrapperFunction(init);
|
|
90
89
|
if (!inner)
|
|
91
90
|
return undefined;
|
|
@@ -100,8 +99,20 @@ export const getAsapWrapperDetails = (init) => {
|
|
|
100
99
|
if (innerCallExpression.arguments.length === 0)
|
|
101
100
|
return undefined;
|
|
102
101
|
const callback = innerCallExpression.arguments[0];
|
|
103
|
-
if (callback
|
|
104
|
-
|
|
102
|
+
if (!callback)
|
|
103
|
+
return undefined;
|
|
104
|
+
if (callback.type === "Identifier") {
|
|
105
|
+
if (callback.name !== outerParameter.name)
|
|
106
|
+
return undefined;
|
|
107
|
+
if (inner.params.length > 0)
|
|
108
|
+
return undefined;
|
|
109
|
+
return {
|
|
110
|
+
outerParameterName: outerParameter.name,
|
|
111
|
+
innerParameterName,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (callback.type !== "ArrowFunctionExpression" &&
|
|
115
|
+
callback.type !== "FunctionExpression") {
|
|
105
116
|
return undefined;
|
|
106
117
|
}
|
|
107
118
|
if (callback.params.length > 0)
|
|
@@ -109,21 +120,15 @@ export const getAsapWrapperDetails = (init) => {
|
|
|
109
120
|
const callbackCallExpression = getFunctionCallExpression(callback);
|
|
110
121
|
if (!callbackCallExpression)
|
|
111
122
|
return undefined;
|
|
112
|
-
|
|
113
|
-
if (!forwardedArgumentsName)
|
|
114
|
-
return undefined;
|
|
115
|
-
if (innerParameterName) {
|
|
116
|
-
if (forwardedArgumentsName !== innerParameterName)
|
|
117
|
-
return undefined;
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
if (forwardedArgumentsName !== "arguments")
|
|
121
|
-
return undefined;
|
|
123
|
+
if (innerParameterName === undefined) {
|
|
122
124
|
if (callback.type !== "ArrowFunctionExpression")
|
|
123
125
|
return undefined;
|
|
124
126
|
if (inner.type !== "FunctionExpression")
|
|
125
127
|
return undefined;
|
|
126
128
|
}
|
|
129
|
+
const forwardedArgumentsName = getForwardedArgumentsIdentifier(callbackCallExpression, outerParameter.name);
|
|
130
|
+
if (!forwardedArgumentsName)
|
|
131
|
+
return undefined;
|
|
127
132
|
return {
|
|
128
133
|
outerParameterName: outerParameter.name,
|
|
129
134
|
innerParameterName,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const getStatementCallExpression = (statement) => {
|
|
2
|
+
if (statement.type === "ExpressionStatement" &&
|
|
3
|
+
statement.expression.type === "CallExpression") {
|
|
4
|
+
return statement.expression;
|
|
5
|
+
}
|
|
6
|
+
if (statement.type === "ReturnStatement") {
|
|
7
|
+
if (statement.argument?.type !== "CallExpression")
|
|
8
|
+
return undefined;
|
|
9
|
+
return statement.argument;
|
|
10
|
+
}
|
|
11
|
+
if (statement.type === "BlockStatement") {
|
|
12
|
+
const firstStatement = statement.body[0];
|
|
13
|
+
if (!firstStatement || statement.body.length !== 1)
|
|
14
|
+
return undefined;
|
|
15
|
+
return getStatementCallExpression(firstStatement);
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
};
|
|
19
|
+
export const getDirectScheduledCallbackName = (body) => {
|
|
20
|
+
const maybeIf = body.body.at(-1);
|
|
21
|
+
if (!maybeIf)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (maybeIf.type !== "IfStatement")
|
|
24
|
+
return undefined;
|
|
25
|
+
if (!maybeIf.alternate)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (maybeIf.test.type !== "Identifier")
|
|
28
|
+
return undefined;
|
|
29
|
+
const schedulerName = maybeIf.test.name;
|
|
30
|
+
const schedulerCall = getStatementCallExpression(maybeIf.consequent);
|
|
31
|
+
if (!schedulerCall)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (schedulerCall.callee.type !== "Identifier")
|
|
34
|
+
return undefined;
|
|
35
|
+
if (schedulerCall.callee.name !== schedulerName)
|
|
36
|
+
return undefined;
|
|
37
|
+
const schedulerCallback = schedulerCall.arguments[0];
|
|
38
|
+
if (schedulerCall.arguments.length !== 1)
|
|
39
|
+
return undefined;
|
|
40
|
+
if (schedulerCallback?.type !== "Identifier")
|
|
41
|
+
return undefined;
|
|
42
|
+
const fallbackCall = getStatementCallExpression(maybeIf.alternate);
|
|
43
|
+
if (!fallbackCall)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (fallbackCall.callee.type !== "Identifier")
|
|
46
|
+
return undefined;
|
|
47
|
+
if (fallbackCall.callee.name !== "setTimeout")
|
|
48
|
+
return undefined;
|
|
49
|
+
if (fallbackCall.arguments.length !== 2)
|
|
50
|
+
return undefined;
|
|
51
|
+
const fallbackCallback = fallbackCall.arguments[0];
|
|
52
|
+
const fallbackDelay = fallbackCall.arguments[1];
|
|
53
|
+
if (fallbackCallback?.type !== "Identifier")
|
|
54
|
+
return undefined;
|
|
55
|
+
if (fallbackCallback.name !== schedulerCallback.name)
|
|
56
|
+
return undefined;
|
|
57
|
+
if (fallbackDelay?.type !== "NumericLiteral")
|
|
58
|
+
return undefined;
|
|
59
|
+
if (fallbackDelay.value !== 0)
|
|
60
|
+
return undefined;
|
|
61
|
+
return schedulerCallback.name;
|
|
62
|
+
};
|
|
@@ -3,14 +3,13 @@ export const getForwardedArgumentsIdentifier = (callbackCallExpression, outerPar
|
|
|
3
3
|
if (callee.type === "Identifier") {
|
|
4
4
|
if (callee.name !== outerParameterName)
|
|
5
5
|
return undefined;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return spreadArgument.argument.name;
|
|
6
|
+
const firstArgument = callbackCallExpression.arguments[0];
|
|
7
|
+
if (callbackCallExpression.arguments.length === 1 &&
|
|
8
|
+
firstArgument?.type === "SpreadElement" &&
|
|
9
|
+
firstArgument.argument.type === "Identifier") {
|
|
10
|
+
return firstArgument.argument.name;
|
|
11
|
+
}
|
|
12
|
+
return "$invoked";
|
|
14
13
|
}
|
|
15
14
|
if (callee.type !== "MemberExpression" ||
|
|
16
15
|
callee.computed ||
|
|
@@ -21,21 +20,22 @@ export const getForwardedArgumentsIdentifier = (callbackCallExpression, outerPar
|
|
|
21
20
|
}
|
|
22
21
|
if (callee.property.name === "apply") {
|
|
23
22
|
if (callbackCallExpression.arguments.length !== 2)
|
|
24
|
-
return
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
return
|
|
28
|
-
|
|
23
|
+
return "$invoked";
|
|
24
|
+
const argumentsValue = callbackCallExpression.arguments[1];
|
|
25
|
+
if (argumentsValue?.type === "Identifier") {
|
|
26
|
+
return argumentsValue.name;
|
|
27
|
+
}
|
|
28
|
+
return "$invoked";
|
|
29
29
|
}
|
|
30
30
|
if (callee.property.name === "call") {
|
|
31
31
|
if (callbackCallExpression.arguments.length !== 2)
|
|
32
|
-
return
|
|
32
|
+
return "$invoked";
|
|
33
33
|
const spreadArgument = callbackCallExpression.arguments[1];
|
|
34
|
-
if (spreadArgument?.type
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return
|
|
34
|
+
if (spreadArgument?.type === "SpreadElement" &&
|
|
35
|
+
spreadArgument.argument.type === "Identifier") {
|
|
36
|
+
return spreadArgument.argument.name;
|
|
37
|
+
}
|
|
38
|
+
return "$invoked";
|
|
39
39
|
}
|
|
40
40
|
return undefined;
|
|
41
41
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const SCHEDULER_METHOD_NAMES = new Set([
|
|
2
|
+
"asap",
|
|
3
|
+
"nextTick",
|
|
4
|
+
"queueMicrotask",
|
|
5
|
+
"setImmediate",
|
|
6
|
+
]);
|
|
7
|
+
export const isAsapCallee = (call) => {
|
|
8
|
+
const callee = call.callee;
|
|
9
|
+
if (callee.type === "Identifier") {
|
|
10
|
+
return SCHEDULER_METHOD_NAMES.has(callee.name);
|
|
11
|
+
}
|
|
12
|
+
if (callee.type === "MemberExpression") {
|
|
13
|
+
if (!callee.computed &&
|
|
14
|
+
callee.property.type === "Identifier" &&
|
|
15
|
+
SCHEDULER_METHOD_NAMES.has(callee.property.name)) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (callee.computed &&
|
|
19
|
+
callee.property.type === "StringLiteral" &&
|
|
20
|
+
SCHEDULER_METHOD_NAMES.has(callee.property.value)) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
};
|
|
@@ -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": 99.
|
|
6
|
-
"evaluatedAt": "2026-02-
|
|
7
|
-
"changedLines":
|
|
8
|
-
"durationSeconds":
|
|
5
|
+
"diffSizePercent": 99.99433042295045,
|
|
6
|
+
"evaluatedAt": "2026-02-28T11:41:18.249Z",
|
|
7
|
+
"changedLines": 14,
|
|
8
|
+
"durationSeconds": 39.792677125000004,
|
|
9
9
|
"stableNames": 1358
|
|
10
10
|
}
|
|
11
11
|
},
|