@abide/abide 0.123.2 → 0.124.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/ABIDE.md +8 -5
- package/CHANGELOG.md +58 -0
- package/bin/abide.ts +36 -65
- package/docs/REGISTRY.md +45 -12
- package/docs/RULEBOOK.md +24 -14
- package/docs/abide.md +999 -459
- package/package.json +1 -1
- package/src/compiler/ARRAY_MUTATORS.ts +20 -0
- package/src/compiler/Diagnostics.ts +198 -0
- package/src/compiler/KeptChecker.ts +97 -0
- package/src/compiler/LoweredFile.ts +609 -0
- package/src/compiler/Lowering.ts +18 -1
- package/src/compiler/PositionedRefusal.ts +1 -1
- package/src/compiler/SHARED_NAMES.ts +2 -0
- package/src/compiler/ShadowHost.ts +670 -0
- package/src/compiler/ShadowMap.ts +1 -1
- package/src/compiler/TypeSession.ts +76 -1743
- package/src/compiler/appLayout.ts +28 -20
- package/src/compiler/appLints.ts +109 -0
- package/src/compiler/argsDefaultsIn.ts +1 -1
- package/src/compiler/checkApp.ts +64 -68
- package/src/compiler/checkedShadow.ts +2 -2
- package/src/compiler/classifyRead.ts +16 -1
- package/src/compiler/compileApp.ts +102 -71
- package/src/compiler/declaredExports.ts +46 -21
- package/src/compiler/diagnoseSources.ts +232 -0
- package/src/compiler/emitClient.ts +1 -1
- package/src/compiler/formatAbide.ts +7 -8
- package/src/compiler/handlersUnder.ts +32 -63
- package/src/compiler/lineOf.ts +0 -19
- package/src/compiler/matchersOf.ts +3 -3
- package/src/compiler/mountsOf.ts +3 -3
- package/src/compiler/reactiveReads.ts +235 -0
- package/src/compiler/reactiveTypes.ts +13 -0
- package/src/compiler/readSources.ts +16 -18
- package/src/compiler/readsIn.ts +181 -82
- package/src/compiler/routesDeclaration.ts +46 -0
- package/src/compiler/scaffold.ts +7 -2
- package/src/compiler/serveLanguage.ts +46 -74
- package/src/compiler/sharedModuleWrites.ts +1 -1
- package/src/compiler/splitImports.ts +2 -2
- package/src/compiler/templateWarnings.ts +1 -2
- package/src/compiler/trackingWarnings.ts +1 -1
- package/src/server/CLIENT_BUILD.ts +4 -32
- package/src/server/DesktopSession.ts +213 -0
- package/src/server/Followers.ts +399 -0
- package/src/server/MODULE_QUERIES.ts +6 -2
- package/src/server/PageRender.ts +201 -0
- package/src/server/RESUME_MILLISECONDS.ts +2 -0
- package/src/server/abideModules.ts +7 -7
- package/src/server/answerFailure.ts +3 -2
- package/src/server/answerRequest.ts +16 -369
- package/src/server/answerRpc.ts +48 -302
- package/src/server/answerSocket.ts +41 -490
- package/src/server/appBuild.ts +377 -0
- package/src/server/appKit.ts +1 -1
- package/src/server/appPlugins.ts +15 -17
- package/src/server/appTree.ts +6 -5
- package/src/server/argsContract.ts +209 -0
- package/src/server/bridgeRelay.ts +153 -65
- package/src/server/claudeCode.ts +30 -127
- package/src/server/config.ts +6 -7
- package/src/server/createApp.ts +38 -66
- package/src/server/csp.ts +1 -1
- package/src/server/deferredBuilds.ts +3 -16
- package/src/server/devWorker.ts +11 -15
- package/src/server/faceOf.ts +1 -1
- package/src/server/generatedSurfaces.ts +2 -1
- package/src/server/handlerFileMount.ts +40 -0
- package/src/server/index.ts +3 -3
- package/src/server/installServer.ts +5 -9
- package/src/server/invokeHandler.ts +230 -0
- package/src/server/mountHandlers.ts +184 -0
- package/src/server/openDesktopWindow.ts +308 -0
- package/src/server/packageDirectory.ts +14 -0
- package/src/server/preload.ts +21 -2
- package/src/server/principal.ts +5 -4
- package/src/server/remote.ts +2 -2
- package/src/server/render.ts +31 -59
- package/src/server/requestScope.ts +5 -36
- package/src/server/runCompiled.ts +1 -1
- package/src/server/runDesktop.ts +20 -448
- package/src/server/seedBuffer.ts +12 -12
- package/src/server/serveDev.ts +24 -58
- package/src/server/servedApp.ts +390 -0
- package/src/server/shell.ts +1 -1
- package/src/server/signInChanged.ts +20 -0
- package/src/server/surfaceOf.ts +3 -2
- package/src/server/versionOf.ts +7 -16
- package/src/shared/RPC_SERVER.ts +27 -31
- package/src/shared/Schema.ts +1 -2
- package/src/shared/applyPatch.ts +1 -1
- package/src/shared/index.ts +1 -1
- package/src/shared/{note.ts → issueReport.ts} +22 -0
- package/src/shared/loadCall.ts +66 -0
- package/src/shared/muxFrames.ts +1 -1
- package/src/shared/reactive/Keyed.ts +24 -16
- package/src/shared/reactive/Reactive.ts +37 -991
- package/src/shared/reactive/argsContract.ts +131 -4
- package/src/shared/reactive/byOf.ts +2 -5
- package/src/shared/reactive/callLoad.ts +8 -14
- package/src/shared/reactive/cellShape.ts +734 -0
- package/src/shared/reactive/index.ts +12 -23
- package/src/shared/reactive/pairReactive.ts +5 -3
- package/src/shared/reactive/patchLog.ts +79 -0
- package/src/shared/reactive/patchMarks.ts +34 -0
- package/src/shared/reactive/producer.ts +121 -0
- package/src/shared/reactive/recordWrites.ts +11 -14
- package/src/shared/reactive/scoped.ts +3 -2
- package/src/shared/reactive/selections.ts +209 -0
- package/src/shared/reactive/share.ts +4 -3
- package/src/shared/reactive/watch.ts +3 -4
- package/src/shared/rpc.ts +20 -24
- package/src/shared/validateJson.ts +1 -2
- package/src/shared/writePath.ts +29 -0
- package/src/ui/ArmRegion.ts +10 -4
- package/src/ui/Level.ts +11 -20
- package/src/ui/LevelChain.ts +272 -0
- package/src/ui/Router.ts +106 -313
- package/src/ui/Scope.ts +17 -3
- package/src/ui/TryRegion.ts +22 -23
- package/src/ui/bindSpread.ts +2 -4
- package/src/ui/listenForRoutes.ts +3 -10
- package/src/ui/outboxQueue.ts +23 -11
- package/src/ui/outcomeOf.ts +120 -0
- package/src/ui/reconcile.ts +4 -6
- package/src/ui/routing.ts +2 -1
- package/src/ui/rows.ts +2 -2
- package/src/ui/setAttribute.ts +12 -3
- package/src/ui/socketWire.ts +28 -13
- package/src/ui/wire.ts +9 -10
- package/src/compiler/Finding.ts +0 -2
- package/src/compiler/Refusals.ts +0 -65
- package/src/compiler/formatDiagnosis.ts +0 -20
- package/src/server/appDirectories.ts +0 -9
- package/src/server/argsFor.ts +0 -39
- package/src/server/buildDirectory.ts +0 -10
- package/src/server/coerceArgs.ts +0 -109
- package/src/server/derivedArgs.ts +0 -26
- package/src/server/runBuild.ts +0 -24
- package/src/server/serveBuild.ts +0 -144
- package/src/server/testBuild.ts +0 -220
- package/src/shared/LOAD_OFFLINE.ts +0 -15
- package/src/shared/LOAD_SIGNAL.ts +0 -10
- package/src/shared/issuesOf.ts +0 -18
- package/src/shared/reactive/ENTRY_LIVES.ts +0 -7
- package/src/shared/reactive/FOLLOWED.ts +0 -8
- package/src/shared/reactive/PATCHES.ts +0 -11
- package/src/shared/reactive/PATCH_SINKS.ts +0 -26
- package/src/shared/reactive/canonicalKey.ts +0 -95
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The methods an array declares that change it in place.
|
|
3
|
+
*
|
|
4
|
+
* A constants leaf, with no imports of its own.
|
|
5
|
+
*
|
|
6
|
+
* 31.9 — a call of one on a name bound to a `Reactive` is lifted to a write through the receiver's
|
|
7
|
+
* path only where the receiver's TYPE is an array (`liftedMutators` in `readsIn`): the name says
|
|
8
|
+
* which method, the type says whose.
|
|
9
|
+
*/
|
|
10
|
+
export const ARRAY_MUTATORS: ReadonlySet<string> = new Set([
|
|
11
|
+
'copyWithin',
|
|
12
|
+
'fill',
|
|
13
|
+
'pop',
|
|
14
|
+
'push',
|
|
15
|
+
'reverse',
|
|
16
|
+
'shift',
|
|
17
|
+
'sort',
|
|
18
|
+
'splice',
|
|
19
|
+
'unshift',
|
|
20
|
+
])
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { relative, resolve } from 'node:path' // bun exposes no path helpers of its own
|
|
2
|
+
|
|
3
|
+
import { isIgnored } from './isIgnored.ts'
|
|
4
|
+
import { lineOf } from './lineOf.ts'
|
|
5
|
+
import { PositionedRefusal } from './PositionedRefusal.ts'
|
|
6
|
+
|
|
7
|
+
// EVERYTHING THE COMPILER HAS TO SAY, IN ONE PLACE: what a finding is, where it lands on the line an
|
|
8
|
+
// author wrote, which an author silenced, the order the lot is reported in, and the one line each is
|
|
9
|
+
// printed as. `abide build`, `abide dev`, `abide check`, `abide format` and `abide lsp` all read
|
|
10
|
+
// findings off this, so none of them decides for itself what a refusal does or how a warning reads.
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* One thing the checker said, placed in the file the author wrote.
|
|
14
|
+
*
|
|
15
|
+
* 38.3 — line and column from 1.
|
|
16
|
+
*/
|
|
17
|
+
export type Diagnosis = {
|
|
18
|
+
path: string
|
|
19
|
+
line: number
|
|
20
|
+
column: number
|
|
21
|
+
code: number
|
|
22
|
+
category: 'error' | 'warning' | 'suggestion' | 'message'
|
|
23
|
+
message: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** A warning or a refusal at a projection offset. */
|
|
27
|
+
export type Finding = { at: number; message: string }
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Where everything a compile finds goes, each at the file it was found in.
|
|
31
|
+
*
|
|
32
|
+
* TWO MODES AND ONE CALL for a refusal: a build stops at one, so a throwing sink throws it; `abide
|
|
33
|
+
* check` reports every one at its file and goes on (38.33), so a collecting sink keeps each as a
|
|
34
|
+
* finding at the file's first line. A warning is kept either way — it does not stop a build — and so
|
|
35
|
+
* is what the checker says (`checked`). Every stage takes this and nothing else, so no stage decides
|
|
36
|
+
* for itself what a refusal does, and none spells a path its own way: a file is named relative to
|
|
37
|
+
* `root` or absolutely, and kept absolute.
|
|
38
|
+
*/
|
|
39
|
+
export class Diagnostics {
|
|
40
|
+
/** Every refusal kept, in the order met; empty in a throwing sink. */
|
|
41
|
+
readonly refused: Diagnosis[] = []
|
|
42
|
+
/** Every warning the compiler raised, in the order met (14, 32.14, 11.30, 18.15). */
|
|
43
|
+
readonly warnings: Diagnosis[] = []
|
|
44
|
+
/** What the checker said of each file (38.3). */
|
|
45
|
+
readonly checked: Diagnosis[] = []
|
|
46
|
+
/** What a file below the root is named relative to. */
|
|
47
|
+
readonly root: string
|
|
48
|
+
/** Whether a refusal is kept and the compile goes on, rather than thrown. */
|
|
49
|
+
readonly collecting: boolean
|
|
50
|
+
|
|
51
|
+
constructor(root: string, collecting: boolean) {
|
|
52
|
+
this.root = root
|
|
53
|
+
this.collecting = collecting
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Every finding, in the order reported: the refusals, the warnings, then the checker's. */
|
|
57
|
+
get findings(): Diagnosis[] {
|
|
58
|
+
return [...this.refused, ...this.warnings, ...this.checked]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Refuses at `file`, below the root or absolute: `thrown` is thrown, or kept. Handed the file's
|
|
63
|
+
* `text`, a `PositionedRefusal` is placed on its line and column, and thrown as that line.
|
|
64
|
+
*/
|
|
65
|
+
at(file: string, thrown: unknown, text?: string): void {
|
|
66
|
+
const positioned =
|
|
67
|
+
text !== undefined && thrown instanceof PositionedRefusal
|
|
68
|
+
if (!this.collecting && !positioned) throw thrown
|
|
69
|
+
const diagnosis = diagnosisAt(
|
|
70
|
+
resolve(this.root, file),
|
|
71
|
+
positioned ? text : undefined,
|
|
72
|
+
positioned ? thrown.offset : 0,
|
|
73
|
+
'error',
|
|
74
|
+
thrown instanceof Error ? thrown.message : String(thrown),
|
|
75
|
+
)
|
|
76
|
+
if (!this.collecting)
|
|
77
|
+
throw new Error(formatDiagnosis(diagnosis, process.cwd()))
|
|
78
|
+
this.refused.push(diagnosis)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* What another stage kept, as this one takes it: every one kept, or every one thrown as one
|
|
83
|
+
* error, each at its file — a build that stops names all it found rather than a first one and a
|
|
84
|
+
* second run (11.37).
|
|
85
|
+
*/
|
|
86
|
+
adopt(found: readonly Diagnosis[]): void {
|
|
87
|
+
if (found.length === 0) return
|
|
88
|
+
if (this.collecting) {
|
|
89
|
+
this.refused.push(...found)
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
const lines: string[] = []
|
|
93
|
+
for (const one of found) lines.push(formatDiagnosis(one, process.cwd()))
|
|
94
|
+
throw new Error(lines.join('\n'))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Keeps `found` as warnings: the build goes on. */
|
|
98
|
+
warn(found: readonly Diagnosis[]): void {
|
|
99
|
+
this.warnings.push(...found)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Keeps what the checker said. */
|
|
103
|
+
check(found: readonly Diagnosis[]): void {
|
|
104
|
+
this.checked.push(...found)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** abide's own finding at `offset` into `text`, or at line 0 where the text was not handed in. */
|
|
109
|
+
export function diagnosisAt(
|
|
110
|
+
path: string,
|
|
111
|
+
text: string | undefined,
|
|
112
|
+
offset: number,
|
|
113
|
+
category: Diagnosis['category'],
|
|
114
|
+
message: string,
|
|
115
|
+
): Diagnosis {
|
|
116
|
+
return {
|
|
117
|
+
path,
|
|
118
|
+
...(text === undefined ? { line: 0, column: 0 } : lineOf(text, offset)),
|
|
119
|
+
code: 0,
|
|
120
|
+
category,
|
|
121
|
+
message,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Each of `findings`, at an offset `place` maps into the file at `path` the author wrote, as a
|
|
127
|
+
* finding on its line — or on line 0 where the text was not handed in.
|
|
128
|
+
*
|
|
129
|
+
* 14.19 — `reads`: they are warnings on reactive reads, and one the line above silences with
|
|
130
|
+
* `abide-ignore` and its clause is left out. No other finding is silenced so.
|
|
131
|
+
*/
|
|
132
|
+
export function placedFindings(
|
|
133
|
+
path: string,
|
|
134
|
+
text: string | undefined,
|
|
135
|
+
findings: readonly Finding[],
|
|
136
|
+
place: (at: number) => number,
|
|
137
|
+
category: Diagnosis['category'],
|
|
138
|
+
reads = false,
|
|
139
|
+
): Diagnosis[] {
|
|
140
|
+
const placed: Diagnosis[] = []
|
|
141
|
+
for (const finding of findings) {
|
|
142
|
+
const offset = place(finding.at)
|
|
143
|
+
if (
|
|
144
|
+
reads &&
|
|
145
|
+
text !== undefined &&
|
|
146
|
+
isIgnored(text, offset, finding.message)
|
|
147
|
+
)
|
|
148
|
+
continue
|
|
149
|
+
placed.push(diagnosisAt(path, text, offset, category, finding.message))
|
|
150
|
+
}
|
|
151
|
+
return placed
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Orders findings by file, then line, then column. */
|
|
155
|
+
export function byPlace(one: Diagnosis, two: Diagnosis): number {
|
|
156
|
+
return (
|
|
157
|
+
one.path.localeCompare(two.path) ||
|
|
158
|
+
one.line - two.line ||
|
|
159
|
+
one.column - two.column
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* One finding as one `tsc`-style line.
|
|
165
|
+
*
|
|
166
|
+
* ONE LINE A FINDING, in the shape `tsc` and every editor's problem matcher already read:
|
|
167
|
+
* `file:line:column - error TS2322: …`, the path relative to `from`. A finding with no line — a
|
|
168
|
+
* whole-file or whole-app refusal — names the file alone.
|
|
169
|
+
*/
|
|
170
|
+
export function formatDiagnosis(diagnosis: Diagnosis, from: string): string {
|
|
171
|
+
const path = relative(from, diagnosis.path) || diagnosis.path
|
|
172
|
+
const where =
|
|
173
|
+
diagnosis.line === 0
|
|
174
|
+
? path
|
|
175
|
+
: `${path}:${diagnosis.line}:${diagnosis.column}`
|
|
176
|
+
const code = diagnosis.code === 0 ? '' : ` TS${diagnosis.code}`
|
|
177
|
+
return `${where} - ${diagnosis.category}${code}: ${diagnosis.message}`
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Writes each error and warning in `found` as its line, relative to where the command was run, and
|
|
182
|
+
* answers how many of each — what every command that reports findings prints. A suggestion or a
|
|
183
|
+
* message is neither, and is not written.
|
|
184
|
+
*/
|
|
185
|
+
export function printDiagnoses(
|
|
186
|
+
found: readonly Diagnosis[],
|
|
187
|
+
write: (line: string) => void,
|
|
188
|
+
): { errors: number; warnings: number } {
|
|
189
|
+
let errors = 0
|
|
190
|
+
let warnings = 0
|
|
191
|
+
for (const diagnosis of found) {
|
|
192
|
+
if (diagnosis.category === 'error') errors += 1
|
|
193
|
+
else if (diagnosis.category === 'warning') warnings += 1
|
|
194
|
+
else continue
|
|
195
|
+
write(formatDiagnosis(diagnosis, process.cwd()))
|
|
196
|
+
}
|
|
197
|
+
return { errors, warnings }
|
|
198
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type FSWatcher, watch } from 'node:fs' // bun exposes no file watcher of its own
|
|
2
|
+
|
|
3
|
+
import { type AppChecker, openChecker } from './compileApp.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* An app's checker kept for as long as a server runs, opened when first asked for and told what its
|
|
7
|
+
* watchers see move.
|
|
8
|
+
*
|
|
9
|
+
* `abide dev` and `abide lsp` keep one each, because spawning a checker is most of what a compile
|
|
10
|
+
* costs. WHAT KEEPING ONE TAKES is here rather than in either: one whose project moved
|
|
11
|
+
* (`AppChecker.current`) is closed and another opened, and one a question threw from is dropped —
|
|
12
|
+
* the checker's own process dying is a throw too, and a session nobody can tell apart from a dead
|
|
13
|
+
* one is not one to keep. `heard` is told every move after the checker is, so what it schedules
|
|
14
|
+
* reads a checker that already knows.
|
|
15
|
+
*/
|
|
16
|
+
export class KeptChecker {
|
|
17
|
+
readonly root: string
|
|
18
|
+
private readonly heard: () => void
|
|
19
|
+
private readonly watchers: FSWatcher[] = []
|
|
20
|
+
private readonly watched = new Set<string>()
|
|
21
|
+
private checker: Promise<AppChecker> | undefined
|
|
22
|
+
private readonly open: (root: string) => Promise<AppChecker>
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
root: string,
|
|
26
|
+
heard: () => void,
|
|
27
|
+
open: (root: string) => Promise<AppChecker> = openChecker,
|
|
28
|
+
) {
|
|
29
|
+
this.root = root
|
|
30
|
+
this.heard = heard
|
|
31
|
+
this.open = open
|
|
32
|
+
this.watch(root, true)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A checker on the project as it stands: the one kept where it still is, or a fresh one. */
|
|
36
|
+
async live(): Promise<AppChecker> {
|
|
37
|
+
const kept = this.checker
|
|
38
|
+
if (kept !== undefined) {
|
|
39
|
+
const checker = await kept.catch(() => undefined)
|
|
40
|
+
if (checker?.current()) return checker
|
|
41
|
+
if (this.checker === kept) await this.drop()
|
|
42
|
+
}
|
|
43
|
+
this.checker ??= this.open(this.root)
|
|
44
|
+
return this.checker
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** `question` asked of a live checker; a throw drops it, so the next question opens another. */
|
|
48
|
+
async run<Answer>(
|
|
49
|
+
question: (checker: AppChecker) => Promise<Answer>,
|
|
50
|
+
): Promise<Answer> {
|
|
51
|
+
try {
|
|
52
|
+
return await question(await this.live())
|
|
53
|
+
} catch (thrown) {
|
|
54
|
+
await this.drop()
|
|
55
|
+
throw thrown
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Watches `directory` too — a linked package's, outside the root — once for the session. */
|
|
60
|
+
watch(directory: string, recursive = false): void {
|
|
61
|
+
if (this.watched.has(directory)) return
|
|
62
|
+
this.watched.add(directory)
|
|
63
|
+
this.watchers.push(
|
|
64
|
+
watch(directory, { recursive }, (_event, filename) =>
|
|
65
|
+
this.saw(
|
|
66
|
+
filename === null ? undefined : `${directory}/${filename}`,
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Records a move at `path`, or one nobody could place, then tells `heard`. */
|
|
73
|
+
saw(path: string | undefined): void {
|
|
74
|
+
void this.checker?.then(
|
|
75
|
+
(checker) => checker.saw(path),
|
|
76
|
+
() => {},
|
|
77
|
+
)
|
|
78
|
+
this.heard()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Stops watching and closes the checker. */
|
|
82
|
+
async close(): Promise<void> {
|
|
83
|
+
for (const watcher of this.watchers) watcher.close()
|
|
84
|
+
this.watchers.length = 0
|
|
85
|
+
await this.drop()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async drop(): Promise<void> {
|
|
89
|
+
const dropped = this.checker
|
|
90
|
+
this.checker = undefined
|
|
91
|
+
try {
|
|
92
|
+
await (await dropped)?.close()
|
|
93
|
+
} catch {
|
|
94
|
+
// Already gone, which is what closing it was for.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|