@typeonce/oxlint-plugin-effect-machine 0.26.1 → 0.27.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/README.md +151 -9
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/ambient.d.ts +6 -0
- package/dist/internal/ambient.d.ts.map +1 -0
- package/dist/internal/ambient.js +118 -0
- package/dist/internal/ambient.js.map +1 -0
- package/dist/internal/ast.d.ts +7 -0
- package/dist/internal/ast.d.ts.map +1 -0
- package/dist/internal/ast.js +62 -0
- package/dist/internal/ast.js.map +1 -0
- package/dist/internal/imports.d.ts +1 -0
- package/dist/internal/imports.d.ts.map +1 -1
- package/dist/internal/imports.js +19 -9
- package/dist/internal/imports.js.map +1 -1
- package/dist/internal/planning.d.ts +3 -0
- package/dist/internal/planning.d.ts.map +1 -1
- package/dist/internal/planning.js +54 -7
- package/dist/internal/planning.js.map +1 -1
- package/dist/internal/rules/noAsyncPlanningCallback.d.ts.map +1 -1
- package/dist/internal/rules/noAsyncPlanningCallback.js +18 -3
- package/dist/internal/rules/noAsyncPlanningCallback.js.map +1 -1
- package/dist/internal/rules/noBrowserApiInPlanning.d.ts +3 -0
- package/dist/internal/rules/noBrowserApiInPlanning.d.ts.map +1 -0
- package/dist/internal/rules/noBrowserApiInPlanning.js +54 -0
- package/dist/internal/rules/noBrowserApiInPlanning.js.map +1 -0
- package/dist/internal/rules/noConflictingInvocationIdentity.d.ts +3 -0
- package/dist/internal/rules/noConflictingInvocationIdentity.d.ts.map +1 -0
- package/dist/internal/rules/noConflictingInvocationIdentity.js +289 -0
- package/dist/internal/rules/noConflictingInvocationIdentity.js.map +1 -0
- package/dist/internal/rules/noNondeterministicPlanning.d.ts +3 -0
- package/dist/internal/rules/noNondeterministicPlanning.d.ts.map +1 -0
- package/dist/internal/rules/noNondeterministicPlanning.js +33 -0
- package/dist/internal/rules/noNondeterministicPlanning.js.map +1 -0
- package/dist/internal/rules/noRedundantResolve.d.ts.map +1 -1
- package/dist/internal/rules/noRedundantResolve.js +41 -15
- package/dist/internal/rules/noRedundantResolve.js.map +1 -1
- package/dist/recommended.d.ts +3 -0
- package/dist/recommended.d.ts.map +1 -1
- package/dist/recommended.js +3 -0
- package/dist/recommended.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +6 -0
- package/src/internal/ambient.ts +134 -0
- package/src/internal/ast.ts +83 -0
- package/src/internal/imports.ts +27 -8
- package/src/internal/planning.ts +69 -7
- package/src/internal/rules/noAsyncPlanningCallback.ts +21 -4
- package/src/internal/rules/noBrowserApiInPlanning.ts +57 -0
- package/src/internal/rules/noConflictingInvocationIdentity.ts +343 -0
- package/src/internal/rules/noNondeterministicPlanning.ts +39 -0
- package/src/internal/rules/noRedundantResolve.ts +48 -16
- package/src/recommended.ts +3 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Effect Machine Oxlint plugin
|
|
2
2
|
|
|
3
3
|
`@typeonce/oxlint-plugin-effect-machine` checks Effect Machine definitions for
|
|
4
|
-
|
|
5
|
-
definitions.
|
|
4
|
+
invalid invocation identities, impure planning, redundant resolvers, and
|
|
5
|
+
one-use intermediate machine definitions.
|
|
6
6
|
|
|
7
7
|
The plugin uses Oxlint's JavaScript plugin interface. Custom JavaScript plugins
|
|
8
8
|
are currently alpha in Oxlint, so keep Oxlint and this package on versions that
|
|
@@ -40,16 +40,24 @@ JSON configurations can list the same rules directly:
|
|
|
40
40
|
"jsPlugins": ["@typeonce/oxlint-plugin-effect-machine"],
|
|
41
41
|
"rules": {
|
|
42
42
|
"effect-machine/no-async-planning-callback": "error",
|
|
43
|
+
"effect-machine/no-browser-api-in-planning": "error",
|
|
44
|
+
"effect-machine/no-conflicting-invocation-identity": "error",
|
|
45
|
+
"effect-machine/no-nondeterministic-planning": "error",
|
|
43
46
|
"effect-machine/no-redundant-resolve": "error",
|
|
44
47
|
"effect-machine/prefer-inline-handle": "error"
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
```
|
|
48
51
|
|
|
49
|
-
The rules are syntax-based
|
|
50
|
-
`.handle(...)` calls, and `.handle(...)`
|
|
51
|
-
same module. They do not resolve
|
|
52
|
-
|
|
52
|
+
The rules are syntax-based and deliberately conservative. They recognize
|
|
53
|
+
`Machine.make(...)`, direct chained `.handle(...)` calls, and `.handle(...)`
|
|
54
|
+
calls on definitions declared in the same module. They do not resolve an
|
|
55
|
+
imported machine definition or guess the result of an arbitrary function call.
|
|
56
|
+
|
|
57
|
+
Planning checks cover initial, transition, resolution, lifecycle, choice,
|
|
58
|
+
initialization, output, history fallback, and invocation declaration
|
|
59
|
+
callbacks. A nested invocation source is state-owned work and is not treated
|
|
60
|
+
as planning.
|
|
53
61
|
|
|
54
62
|
## Rules
|
|
55
63
|
|
|
@@ -72,11 +80,145 @@ const handlers = {
|
|
|
72
80
|
The fixer does not run when the resolver has options, comments, construction
|
|
73
81
|
input, or any other work.
|
|
74
82
|
|
|
83
|
+
Resolver-only reentry uses `.reenter()`:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// Before
|
|
87
|
+
to.local.Ready().resolve(({ target }) => target.from(), { reenter: true })
|
|
88
|
+
|
|
89
|
+
// After `oxlint --fix`
|
|
90
|
+
to.local.Ready().reenter()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
An empty `to.none.resolve(() => {})` is similarly reduced to `to.none`.
|
|
94
|
+
|
|
75
95
|
### `effect-machine/no-async-planning-callback`
|
|
76
96
|
|
|
77
|
-
Rejects
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
Rejects `async` planning callbacks and direct Promise, fetch, timer, or
|
|
98
|
+
scheduling operations during planning. A machine plans synchronously and has
|
|
99
|
+
no lifetime in which to own work started by a transition.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
// Incorrect: the transition starts unowned work.
|
|
103
|
+
const incorrect = {
|
|
104
|
+
Submit: (to) => {
|
|
105
|
+
fetch("/orders", { method: "POST" })
|
|
106
|
+
return to.full.Complete()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Correct: the state owns and cancels the work.
|
|
111
|
+
const correct = {
|
|
112
|
+
Submitting: {
|
|
113
|
+
invoke: (from) =>
|
|
114
|
+
from.effect("submit-order", () => submitOrder())
|
|
115
|
+
.onDone((to) => to.full.Complete())
|
|
116
|
+
.onFailure((to) => to.full.Failed())
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The rule only reports known unshadowed globals. Calls inside the source passed
|
|
122
|
+
to `from.effect`, `from.stream`, or another invocation builder remain valid.
|
|
123
|
+
|
|
124
|
+
### `effect-machine/no-conflicting-invocation-identity`
|
|
125
|
+
|
|
126
|
+
Requires every invocation declared by one state to have a unique lifecycle ID
|
|
127
|
+
and every concurrently owned logic or child process to have a unique runtime
|
|
128
|
+
address.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// Incorrect: both outcomes use the "load" lifecycle ID.
|
|
132
|
+
const incorrect = {
|
|
133
|
+
invoke: (from) => [
|
|
134
|
+
from.effect("load", loadAccount),
|
|
135
|
+
from.timer("load", "10 seconds")
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Correct
|
|
140
|
+
const correct = {
|
|
141
|
+
invoke: (from) => [
|
|
142
|
+
from.effect("load-account", loadAccount),
|
|
143
|
+
from.timer("load-timeout", "10 seconds")
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Duplicate lifecycle IDs make outcome routing ambiguous. Duplicate active
|
|
149
|
+
addresses fail at runtime. If two operations must run sequentially, put them
|
|
150
|
+
in separate states and transition from the first invocation's outcome instead
|
|
151
|
+
of relying on completion timing.
|
|
152
|
+
|
|
153
|
+
The rule compares only identities it can prove equal, such as literals, the
|
|
154
|
+
same binding, static `Machine.childAddress(...)` values, and local
|
|
155
|
+
`Machine.child(...)` descriptors. It checks one state's invocation declaration
|
|
156
|
+
at a time and does not guess whether separate states can be active together.
|
|
157
|
+
|
|
158
|
+
### `effect-machine/no-browser-api-in-planning`
|
|
159
|
+
|
|
160
|
+
Rejects direct access to stateful browser APIs such as `document`,
|
|
161
|
+
`localStorage`, `navigator`, `location`, workers, and browser event APIs during
|
|
162
|
+
planning.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
// Incorrect: transition planning reads ambient storage.
|
|
166
|
+
const incorrect = {
|
|
167
|
+
Restore: (to) =>
|
|
168
|
+
localStorage.getItem("draft") === null
|
|
169
|
+
? to.full.Empty()
|
|
170
|
+
: to.full.Editing()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Correct: state-owned work reads storage and reports an outcome.
|
|
174
|
+
const correct = {
|
|
175
|
+
Restoring: {
|
|
176
|
+
invoke: (from) =>
|
|
177
|
+
from.effect("restore-draft", () => restoreDraft())
|
|
178
|
+
.onDone((to) => to.full.Editing())
|
|
179
|
+
.onFailure((to) => to.full.Empty())
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
If browser work affects the workflow, move it into a state-owned invocation.
|
|
185
|
+
If it only focuses, measures, or renders UI, keep it in the UI adapter. Pure
|
|
186
|
+
data utilities such as `URL`, `URLSearchParams`, `TextEncoder`, and
|
|
187
|
+
`structuredClone` are not reported.
|
|
188
|
+
|
|
189
|
+
### `effect-machine/no-nondeterministic-planning`
|
|
190
|
+
|
|
191
|
+
Rejects direct reads of ambient time or randomness during planning, including
|
|
192
|
+
`Date.now()`, zero-argument `new Date()`, `Math.random()`, crypto randomness,
|
|
193
|
+
performance clocks, `Temporal.Now`, and process clocks.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
// Incorrect: the same event and snapshot can select different results.
|
|
197
|
+
const incorrect = {
|
|
198
|
+
Check: (to) =>
|
|
199
|
+
Date.now() >= deadline
|
|
200
|
+
? to.full.Expired()
|
|
201
|
+
: to.none
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Correct: receive the external fact as part of the event protocol.
|
|
205
|
+
const correct = {
|
|
206
|
+
Check: (to) =>
|
|
207
|
+
to.branches({
|
|
208
|
+
expired: { target: to.full.Expired() },
|
|
209
|
+
current: { target: to.full.Current() }
|
|
210
|
+
}).resolve(({ event, select }) =>
|
|
211
|
+
event.now >= event.deadline
|
|
212
|
+
? select.expired.from()
|
|
213
|
+
: select.current.from()
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Pass the value through machine input or an event when it is already known. If
|
|
219
|
+
the machine must obtain it, produce it in a state-owned invocation and
|
|
220
|
+
transition from the invocation outcome. Deterministic operations such as
|
|
221
|
+
`new Date(event.timestamp)` and `Date.parse(state.createdAt)` remain valid.
|
|
80
222
|
|
|
81
223
|
### `effect-machine/prefer-inline-handle`
|
|
82
224
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ declare const plugin: {
|
|
|
4
4
|
};
|
|
5
5
|
rules: {
|
|
6
6
|
"no-async-planning-callback": import("@oxlint/plugins").Rule;
|
|
7
|
+
"no-browser-api-in-planning": import("@oxlint/plugins").Rule;
|
|
8
|
+
"no-conflicting-invocation-identity": import("@oxlint/plugins").Rule;
|
|
9
|
+
"no-nondeterministic-planning": import("@oxlint/plugins").Rule;
|
|
7
10
|
"no-redundant-resolve": import("@oxlint/plugins").Rule;
|
|
8
11
|
"prefer-inline-handle": import("@oxlint/plugins").Rule;
|
|
9
12
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,MAAM;;;;;;;;;;;;CAYM,CAAA;AAElB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,eAAe,MAAM,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { noAsyncPlanningCallback } from "./internal/rules/noAsyncPlanningCallback.js";
|
|
2
|
+
import { noBrowserApiInPlanning } from "./internal/rules/noBrowserApiInPlanning.js";
|
|
3
|
+
import { noConflictingInvocationIdentity } from "./internal/rules/noConflictingInvocationIdentity.js";
|
|
4
|
+
import { noNondeterministicPlanning } from "./internal/rules/noNondeterministicPlanning.js";
|
|
2
5
|
import { noRedundantResolve } from "./internal/rules/noRedundantResolve.js";
|
|
3
6
|
import { preferInlineHandle } from "./internal/rules/preferInlineHandle.js";
|
|
4
7
|
const plugin = {
|
|
@@ -7,6 +10,9 @@ const plugin = {
|
|
|
7
10
|
},
|
|
8
11
|
rules: {
|
|
9
12
|
"no-async-planning-callback": noAsyncPlanningCallback,
|
|
13
|
+
"no-browser-api-in-planning": noBrowserApiInPlanning,
|
|
14
|
+
"no-conflicting-invocation-identity": noConflictingInvocationIdentity,
|
|
15
|
+
"no-nondeterministic-planning": noNondeterministicPlanning,
|
|
10
16
|
"no-redundant-resolve": noRedundantResolve,
|
|
11
17
|
"prefer-inline-handle": preferInlineHandle
|
|
12
18
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6CAA6C,CAAA;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAA;AAE3E,MAAM,MAAM,GAAG;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,gBAAgB;KACvB;IACD,KAAK,EAAE;QACL,4BAA4B,EAAE,uBAAuB;QACrD,sBAAsB,EAAE,kBAAkB;QAC1C,sBAAsB,EAAE,kBAAkB;KAC3C;CACe,CAAA;AAElB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,eAAe,MAAM,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6CAA6C,CAAA;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAA;AACnF,OAAO,EAAE,+BAA+B,EAAE,MAAM,qDAAqD,CAAA;AACrG,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAA;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAA;AAE3E,MAAM,MAAM,GAAG;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,gBAAgB;KACvB;IACD,KAAK,EAAE;QACL,4BAA4B,EAAE,uBAAuB;QACrD,4BAA4B,EAAE,sBAAsB;QACpD,oCAAoC,EAAE,+BAA+B;QACrE,8BAA8B,EAAE,0BAA0B;QAC1D,sBAAsB,EAAE,kBAAkB;QAC1C,sBAAsB,EAAE,kBAAkB;KAC3C;CACe,CAAA;AAElB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,eAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context, ESTree } from "@oxlint/plugins";
|
|
2
|
+
export declare const asyncOperation: (context: Context, node: ESTree.CallExpression | ESTree.NewExpression) => string | undefined;
|
|
3
|
+
export declare const nondeterministicOperation: (context: Context, node: ESTree.CallExpression | ESTree.NewExpression) => string | undefined;
|
|
4
|
+
export declare const nondeterministicProperty: (context: Context, node: ESTree.MemberExpression) => string | undefined;
|
|
5
|
+
export declare const browserApi: (context: Context, node: ESTree.Expression) => string | undefined;
|
|
6
|
+
//# sourceMappingURL=ambient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ambient.d.ts","sourceRoot":"","sources":["../../src/internal/ambient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAuBtD,eAAO,MAAM,cAAc,GACzB,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,aAAa,KACjD,MAAM,GAAG,SAaX,CAAA;AAED,eAAO,MAAM,yBAAyB,GACpC,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,aAAa,KACjD,MAAM,GAAG,SA6BX,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,gBAAgB,KAC5B,MAAM,GAAG,SAKX,CAAA;AAwCD,eAAO,MAAM,UAAU,GACrB,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,UAAU,KACtB,MAAM,GAAG,SAOX,CAAA"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { canonicalGlobalPath } from "./ast.js";
|
|
2
|
+
const scheduledFunctions = new Set([
|
|
3
|
+
"fetch",
|
|
4
|
+
"queueMicrotask",
|
|
5
|
+
"requestAnimationFrame",
|
|
6
|
+
"requestIdleCallback",
|
|
7
|
+
"setImmediate",
|
|
8
|
+
"setInterval",
|
|
9
|
+
"setTimeout"
|
|
10
|
+
]);
|
|
11
|
+
const promiseMethods = new Set([
|
|
12
|
+
"all",
|
|
13
|
+
"allSettled",
|
|
14
|
+
"any",
|
|
15
|
+
"race",
|
|
16
|
+
"reject",
|
|
17
|
+
"resolve",
|
|
18
|
+
"try"
|
|
19
|
+
]);
|
|
20
|
+
export const asyncOperation = (context, node) => {
|
|
21
|
+
const path = canonicalGlobalPath(context, node.callee);
|
|
22
|
+
if (path === undefined)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (node.type === "NewExpression") {
|
|
25
|
+
return path.length === 1 && path[0] === "Promise" ? "new Promise(...)" : undefined;
|
|
26
|
+
}
|
|
27
|
+
if (path.length === 1 && scheduledFunctions.has(path[0]))
|
|
28
|
+
return `${path[0]}(...)`;
|
|
29
|
+
if (path.length === 2 && path[0] === "Promise" && promiseMethods.has(path[1])) {
|
|
30
|
+
return `Promise.${path[1]}(...)`;
|
|
31
|
+
}
|
|
32
|
+
return path.length === 2 && path[0] === "process" && path[1] === "nextTick"
|
|
33
|
+
? "process.nextTick(...)"
|
|
34
|
+
: undefined;
|
|
35
|
+
};
|
|
36
|
+
export const nondeterministicOperation = (context, node) => {
|
|
37
|
+
const path = canonicalGlobalPath(context, node.callee);
|
|
38
|
+
if (path === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
if (node.type === "NewExpression") {
|
|
41
|
+
return path.length === 1 && path[0] === "Date" && node.arguments.length === 0
|
|
42
|
+
? "new Date()"
|
|
43
|
+
: undefined;
|
|
44
|
+
}
|
|
45
|
+
if (path.length === 1 && path[0] === "Date")
|
|
46
|
+
return "Date()";
|
|
47
|
+
if (path.length === 2 && path[0] === "Date" && path[1] === "now")
|
|
48
|
+
return "Date.now()";
|
|
49
|
+
if (path.length === 2 && path[0] === "Math" && path[1] === "random")
|
|
50
|
+
return "Math.random()";
|
|
51
|
+
if (path.length === 2 &&
|
|
52
|
+
path[0] === "crypto" &&
|
|
53
|
+
(path[1] === "getRandomValues" || path[1] === "randomUUID"))
|
|
54
|
+
return `crypto.${path[1]}(...)`;
|
|
55
|
+
if (path.length === 2 && path[0] === "performance" && path[1] === "now") {
|
|
56
|
+
return "performance.now()";
|
|
57
|
+
}
|
|
58
|
+
if (path.length >= 3 && path[0] === "Temporal" && path[1] === "Now") {
|
|
59
|
+
return `${path.join(".")}()`;
|
|
60
|
+
}
|
|
61
|
+
if (path[0] === "process" &&
|
|
62
|
+
(path.join(".") === "process.hrtime" ||
|
|
63
|
+
path.join(".") === "process.hrtime.bigint" ||
|
|
64
|
+
path.join(".") === "process.uptime"))
|
|
65
|
+
return `${path.join(".")}()`;
|
|
66
|
+
return undefined;
|
|
67
|
+
};
|
|
68
|
+
export const nondeterministicProperty = (context, node) => {
|
|
69
|
+
const path = canonicalGlobalPath(context, node);
|
|
70
|
+
return path?.length === 2 && path[0] === "performance" && path[1] === "timeOrigin"
|
|
71
|
+
? "performance.timeOrigin"
|
|
72
|
+
: undefined;
|
|
73
|
+
};
|
|
74
|
+
const browserRoots = new Set([
|
|
75
|
+
"caches",
|
|
76
|
+
"cookieStore",
|
|
77
|
+
"document",
|
|
78
|
+
"history",
|
|
79
|
+
"indexedDB",
|
|
80
|
+
"localStorage",
|
|
81
|
+
"location",
|
|
82
|
+
"navigator",
|
|
83
|
+
"screen",
|
|
84
|
+
"self",
|
|
85
|
+
"sessionStorage",
|
|
86
|
+
"visualViewport",
|
|
87
|
+
"window"
|
|
88
|
+
]);
|
|
89
|
+
const browserFunctions = new Set([
|
|
90
|
+
"addEventListener",
|
|
91
|
+
"alert",
|
|
92
|
+
"confirm",
|
|
93
|
+
"dispatchEvent",
|
|
94
|
+
"getComputedStyle",
|
|
95
|
+
"matchMedia",
|
|
96
|
+
"open",
|
|
97
|
+
"postMessage",
|
|
98
|
+
"prompt",
|
|
99
|
+
"removeEventListener"
|
|
100
|
+
]);
|
|
101
|
+
const browserConstructors = new Set([
|
|
102
|
+
"BroadcastChannel",
|
|
103
|
+
"EventSource",
|
|
104
|
+
"SharedWorker",
|
|
105
|
+
"WebSocket",
|
|
106
|
+
"Worker",
|
|
107
|
+
"XMLHttpRequest"
|
|
108
|
+
]);
|
|
109
|
+
export const browserApi = (context, node) => {
|
|
110
|
+
const path = canonicalGlobalPath(context, node);
|
|
111
|
+
if (path === undefined || path.length === 0)
|
|
112
|
+
return undefined;
|
|
113
|
+
if (browserRoots.has(path[0]) || browserFunctions.has(path[0]) || browserConstructors.has(path[0])) {
|
|
114
|
+
return path.join(".");
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=ambient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ambient.js","sourceRoot":"","sources":["../../src/internal/ambient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Context, ESTree, Variable } from "@oxlint/plugins";
|
|
2
|
+
export declare const unwrapExpression: (node: ESTree.Expression) => ESTree.Expression;
|
|
3
|
+
export declare const resolvedVariable: (context: Context, node: ESTree.IdentifierReference) => Variable | undefined;
|
|
4
|
+
export declare const isUnshadowedGlobal: (context: Context, node: ESTree.Expression, name: string) => node is ESTree.IdentifierReference;
|
|
5
|
+
export declare const globalPath: (context: Context, node: ESTree.Expression) => ReadonlyArray<string> | undefined;
|
|
6
|
+
export declare const canonicalGlobalPath: (context: Context, node: ESTree.Expression) => ReadonlyArray<string> | undefined;
|
|
7
|
+
//# sourceMappingURL=ast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/internal/ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAS,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAGvE,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,CAAC,UAAU,KAAG,MAAM,CAAC,UAWjE,CAAA;AASD,eAAO,MAAM,gBAAgB,GAC3B,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,mBAAmB,KAC/B,QAAQ,GAAG,SAQb,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,UAAU,EACvB,MAAM,MAAM,KACX,IAAI,IAAI,MAAM,CAAC,mBAYjB,CAAA;AAED,eAAO,MAAM,UAAU,GACrB,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,UAAU,KACtB,aAAa,CAAC,MAAM,CAAC,GAAG,SAa1B,CAAA;AAID,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,EAChB,MAAM,MAAM,CAAC,UAAU,KACtB,aAAa,CAAC,MAAM,CAAC,GAAG,SAK1B,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { staticMemberName } from "./imports.js";
|
|
2
|
+
export const unwrapExpression = (node) => {
|
|
3
|
+
let current = node;
|
|
4
|
+
while (current.type === "ChainExpression" ||
|
|
5
|
+
current.type === "ParenthesizedExpression" ||
|
|
6
|
+
current.type === "TSAsExpression" ||
|
|
7
|
+
current.type === "TSNonNullExpression" ||
|
|
8
|
+
current.type === "TSSatisfiesExpression" ||
|
|
9
|
+
current.type === "TSTypeAssertion")
|
|
10
|
+
current = current.expression;
|
|
11
|
+
return current;
|
|
12
|
+
};
|
|
13
|
+
const referenceIn = (scope, node) => scope.references.find((reference) => reference.identifier === node) ??
|
|
14
|
+
scope.through.find((reference) => reference.identifier === node);
|
|
15
|
+
export const resolvedVariable = (context, node) => {
|
|
16
|
+
let scope = context.sourceCode.getScope(node);
|
|
17
|
+
while (scope !== null) {
|
|
18
|
+
const reference = referenceIn(scope, node);
|
|
19
|
+
if (reference !== undefined)
|
|
20
|
+
return reference.resolved ?? undefined;
|
|
21
|
+
scope = scope.upper;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
};
|
|
25
|
+
export const isUnshadowedGlobal = (context, node, name) => {
|
|
26
|
+
const expression = unwrapExpression(node);
|
|
27
|
+
if (expression.type !== "Identifier" || expression.name !== name)
|
|
28
|
+
return false;
|
|
29
|
+
if (context.sourceCode.isGlobalReference(expression))
|
|
30
|
+
return true;
|
|
31
|
+
let scope = context.sourceCode.getScope(expression);
|
|
32
|
+
while (scope !== null) {
|
|
33
|
+
const reference = referenceIn(scope, expression);
|
|
34
|
+
if (reference !== undefined)
|
|
35
|
+
return reference.resolved === null;
|
|
36
|
+
scope = scope.upper;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
};
|
|
40
|
+
export const globalPath = (context, node) => {
|
|
41
|
+
const expression = unwrapExpression(node);
|
|
42
|
+
if (expression.type === "Identifier") {
|
|
43
|
+
return isUnshadowedGlobal(context, expression, expression.name)
|
|
44
|
+
? [expression.name]
|
|
45
|
+
: undefined;
|
|
46
|
+
}
|
|
47
|
+
if (expression.type !== "MemberExpression")
|
|
48
|
+
return undefined;
|
|
49
|
+
const member = staticMemberName(expression);
|
|
50
|
+
if (member === undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const owner = globalPath(context, expression.object);
|
|
53
|
+
return owner === undefined ? undefined : [...owner, member];
|
|
54
|
+
};
|
|
55
|
+
const ambientQualifiers = new Set(["globalThis", "self", "window"]);
|
|
56
|
+
export const canonicalGlobalPath = (context, node) => {
|
|
57
|
+
const path = globalPath(context, node);
|
|
58
|
+
return path !== undefined && path.length > 1 && ambientQualifiers.has(path[0])
|
|
59
|
+
? path.slice(1)
|
|
60
|
+
: path;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=ast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.js","sourceRoot":"","sources":["../../src/internal/ast.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ export declare const makeMachineBindings: () => MachineBindings;
|
|
|
8
8
|
export declare const recordMachineImport: (bindings: MachineBindings, node: ESTree.ImportDeclaration) => void;
|
|
9
9
|
export declare const hasMachineImport: (bindings: MachineBindings) => boolean;
|
|
10
10
|
export declare const staticMemberName: (node: ESTree.Node) => string | undefined;
|
|
11
|
+
export declare const isMachineMemberCall: (node: ESTree.Node, member: string, bindings: MachineBindings) => node is ESTree.CallExpression;
|
|
11
12
|
export declare const isMachineMakeCall: (node: ESTree.CallExpression, bindings: MachineBindings) => boolean;
|
|
12
13
|
export declare const recordMachineDefinition: (bindings: MachineBindings, node: ESTree.VariableDeclarator) => void;
|
|
13
14
|
export declare const isMachineHandleCall: (node: ESTree.CallExpression, bindings: MachineBindings) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/internal/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAI7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CACjC;AAED,eAAO,MAAM,mBAAmB,QAAO,eAIrC,CAAA;AAIF,eAAO,MAAM,mBAAmB,GAC9B,UAAU,eAAe,EACzB,MAAM,MAAM,CAAC,iBAAiB,KAC7B,IAaF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,UAAU,eAAe,KAAG,OACF,CAAA;AAE3D,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,CAAC,IAAI,KAAG,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/internal/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAI7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CACjC;AAED,eAAO,MAAM,mBAAmB,QAAO,eAIrC,CAAA;AAIF,eAAO,MAAM,mBAAmB,GAC9B,UAAU,eAAe,EACzB,MAAM,MAAM,CAAC,iBAAiB,KAC7B,IAaF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,UAAU,eAAe,KAAG,OACF,CAAA;AAE3D,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,CAAC,IAAI,KAAG,MAAM,GAAG,SAS7D,CAAA;AAqBD,eAAO,MAAM,mBAAmB,GAC9B,MAAM,MAAM,CAAC,IAAI,EACjB,QAAQ,MAAM,EACd,UAAU,eAAe,KACxB,IAAI,IAAI,MAAM,CAAC,cAIgC,CAAA;AAElD,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,CAAC,cAAc,EAC3B,UAAU,eAAe,KACxB,OAOF,CAAA;AAED,eAAO,MAAM,uBAAuB,GAClC,UAAU,eAAe,EACzB,MAAM,MAAM,CAAC,kBAAkB,KAC9B,IAMF,CAAA;AAED,eAAO,MAAM,mBAAmB,GAC9B,MAAM,MAAM,CAAC,cAAc,EAC3B,UAAU,eAAe,KACxB,OAUF,CAAA;AAED,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,CAAC,IAAI,EACjB,QAAQ,MAAM,KACb,IAAI,IAAI,MAAM,CAAC,cAGwB,CAAA"}
|
package/dist/internal/imports.js
CHANGED
|
@@ -19,25 +19,35 @@ export const recordMachineImport = (bindings, node) => {
|
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
export const hasMachineImport = (bindings) => bindings.machine.size > 0 || bindings.namespaces.size > 0;
|
|
22
|
-
export const staticMemberName = (node) =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
export const staticMemberName = (node) => {
|
|
23
|
+
if (node.type !== "MemberExpression")
|
|
24
|
+
return undefined;
|
|
25
|
+
return node.computed
|
|
26
|
+
? node.property.type === "Literal" && typeof node.property.value === "string"
|
|
27
|
+
? node.property.value
|
|
28
|
+
: undefined
|
|
29
|
+
: node.property.type === "Identifier"
|
|
30
|
+
? node.property.name
|
|
31
|
+
: undefined;
|
|
32
|
+
};
|
|
27
33
|
const isNamespaceMachine = (node, bindings) => node.type === "MemberExpression" &&
|
|
28
34
|
!node.computed &&
|
|
29
35
|
node.object.type === "Identifier" &&
|
|
30
36
|
bindings.namespaces.has(node.object.name) &&
|
|
31
37
|
node.property.type === "Identifier" &&
|
|
32
38
|
node.property.name === "Machine";
|
|
39
|
+
const isMachineReference = (node, bindings) => node.type === "Identifier"
|
|
40
|
+
? bindings.machine.has(node.name)
|
|
41
|
+
: isNamespaceMachine(node, bindings);
|
|
42
|
+
export const isMachineMemberCall = (node, member, bindings) => node.type === "CallExpression" &&
|
|
43
|
+
node.callee.type === "MemberExpression" &&
|
|
44
|
+
staticMemberName(node.callee) === member &&
|
|
45
|
+
isMachineReference(node.callee.object, bindings);
|
|
33
46
|
export const isMachineMakeCall = (node, bindings) => {
|
|
34
47
|
if (node.callee.type !== "MemberExpression" ||
|
|
35
48
|
staticMemberName(node.callee) !== "make")
|
|
36
49
|
return false;
|
|
37
|
-
|
|
38
|
-
return receiver.type === "Identifier"
|
|
39
|
-
? bindings.machine.has(receiver.name)
|
|
40
|
-
: isNamespaceMachine(receiver, bindings);
|
|
50
|
+
return isMachineReference(node.callee.object, bindings);
|
|
41
51
|
};
|
|
42
52
|
export const recordMachineDefinition = (bindings, node) => {
|
|
43
53
|
if (node.id.type === "Identifier" &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/internal/imports.ts"],"names":[],"mappings":"AAEA,MAAM,mBAAmB,GAAG,0BAA0B,CAAA;AAQtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAoB,EAAE,CAAC,CAAC;IACzD,WAAW,EAAE,IAAI,GAAG,EAAE;IACtB,OAAO,EAAE,IAAI,GAAG,EAAE;IAClB,UAAU,EAAE,IAAI,GAAG,EAAE;CACtB,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAAC,IAA6B,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAA;AAEvH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,QAAyB,EACzB,IAA8B,EACxB,EAAE;IACR,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,mBAAmB;QAAE,OAAM;IAErD,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,IAAI,SAAS,CAAC,IAAI,KAAK,0BAA0B,EAAE,CAAC;YAClD,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC/C,CAAC;aAAM,IACL,SAAS,CAAC,IAAI,KAAK,iBAAiB;YACpC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,SAAS,EAClD,CAAC;YACD,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAyB,EAAW,EAAE,CACrE,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,CAAA;AAE3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAiB,EAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/internal/imports.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ESTree } from "@oxlint/plugins";
|
|
2
2
|
import { type MachineBindings } from "./imports.js";
|
|
3
3
|
export type PlanningFunction = ESTree.ArrowFunctionExpression | ESTree.Function;
|
|
4
|
+
export declare const enclosingFunction: (node: ESTree.Node) => PlanningFunction | undefined;
|
|
5
|
+
export declare const enclosingPlanningCallback: (node: ESTree.Node, bindings: MachineBindings) => PlanningFunction | undefined;
|
|
6
|
+
export declare const isInvokePlanningCallback: (node: PlanningFunction, bindings: MachineBindings) => boolean;
|
|
4
7
|
export declare const isPlanningCallback: (node: PlanningFunction, bindings: MachineBindings) => boolean;
|
|
5
8
|
//# sourceMappingURL=planning.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../src/internal/planning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../src/internal/planning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE7C,OAAO,EAA0C,KAAK,eAAe,EAAoB,MAAM,cAAc,CAAA;AAE7G,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,uBAAuB,GAAG,MAAM,CAAC,QAAQ,CAAA;AAmH/E,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,CAAC,IAAI,KAAG,gBAAgB,GAAG,SAUxE,CAAA;AAcD,eAAO,MAAM,yBAAyB,GACpC,MAAM,MAAM,CAAC,IAAI,EACjB,UAAU,eAAe,KACxB,gBAAgB,GAAG,SAKrB,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,MAAM,gBAAgB,EACtB,UAAU,eAAe,KACxB,OAOF,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,MAAM,gBAAgB,EACtB,UAAU,eAAe,KACxB,OAiBF,CAAA"}
|