diff --git a/.github/justfile b/.github/justfile index 2ea79ef..6fa72b9 100644 --- a/.github/justfile +++ b/.github/justfile @@ -45,6 +45,7 @@ core: @just gha::_step version-guard-local @just gha::_step version-guard-pr @just gha::_step fmt-check + @just gha::_step lint @just gha::_step build @just gha::_step test-rust @just gha::_step shim diff --git a/justfile b/justfile index b31db8e..51e7cfa 100644 --- a/justfile +++ b/justfile @@ -9,10 +9,10 @@ default: ci: (gha::core) (gha::browser) # Full pre-commit gates, including local consumer smokes (docs/consumers.md). -gates: version-guard-local fmt-check build test-rust test-protocol test-runtime test-wasi test-sockets-node test-ct-runner test-bundle test-version-guard publish-check test-npm examples test-translate conformance sched-seeds shells browsers smoke-tls smoke-c0 +gates: version-guard-local fmt-check lint build test-rust test-protocol test-runtime test-wasi test-sockets-node test-ct-runner test-bundle test-version-guard publish-check test-npm examples test-translate conformance sched-seeds shells browsers smoke-tls smoke-c0 # Fast sanity: builds + native tests + type-checks, no suites. -check: fmt-check build test-rust +check: fmt-check lint build test-rust cd protocol && deno task check cd runtime && deno task check cd wasi && deno task check @@ -22,6 +22,11 @@ check: fmt-check build test-rust fmt-check: cd runtime && deno fmt --check +# The runtime package is lint-clean (`deno lint`, stock rules; generated +# artifacts excluded in runtime/deno.json alongside fmt). +lint: + cd runtime && deno lint + # ----- builders --------------------------------------------------------------- build: diff --git a/runtime/deno.json b/runtime/deno.json index f0ec766..69feffd 100644 --- a/runtime/deno.json +++ b/runtime/deno.json @@ -20,6 +20,13 @@ "tests/fixtures/" ] }, + "lint": { + "exclude": [ + "tests/bindgen/generated/", + "tests/bindgen/fixtures/", + "tests/fixtures/" + ] + }, "publish": { "exclude": [ "tests/" diff --git a/runtime/src/cabi/lift.ts b/runtime/src/cabi/lift.ts index e057470..88c49a1 100644 --- a/runtime/src/cabi/lift.ts +++ b/runtime/src/cabi/lift.ts @@ -1,7 +1,7 @@ // Flat lifting (definitions.py `## Flat Lifting`): core values -> component // values. -import { assert_, NotImplemented, trapIf } from "./trap.ts"; +import { assert_, trapIf } from "./trap.ts"; import { canonicalizeNan32, canonicalizeNan64, diff --git a/runtime/src/cabi/load.ts b/runtime/src/cabi/load.ts index 4af19f2..740ef06 100644 --- a/runtime/src/cabi/load.ts +++ b/runtime/src/cabi/load.ts @@ -1,6 +1,6 @@ // Loading component values from linear memory (definitions.py `## Loading`). -import { assert_, NotImplemented, trapIf } from "./trap.ts"; +import { assert_, trapIf } from "./trap.ts"; import { bytesOf, loadIntS, loadIntU, loadPtr } from "./memory.ts"; import { decodeI32AsFloat, decodeI64AsFloat } from "./float.ts"; import { elemSizeFlags, layoutOf } from "./layout.ts"; @@ -8,12 +8,7 @@ import { convertI32ToChar, loadString } from "./strings.ts"; import { type LiftLowerContext, requireMemory } from "./context.ts"; import { tryLoadNumericList } from "./bulk_lists.ts"; import { liftBorrow, liftOwn } from "./handles.ts"; -import { - type CaseType, - type ComponentValue, - type FieldType, - type ValType, -} from "./types.ts"; +import type { CaseType, ComponentValue, FieldType, ValType } from "./types.ts"; import { liftErrorContext, liftFuture, liftStream } from "./async_values.ts"; export const MAX_LIST_BYTE_LENGTH = (1 << 28) - 1; diff --git a/runtime/src/cabi/lower.ts b/runtime/src/cabi/lower.ts index ddcb257..ba953cd 100644 --- a/runtime/src/cabi/lower.ts +++ b/runtime/src/cabi/lower.ts @@ -1,7 +1,7 @@ // Flat lowering (definitions.py `## Flat Lowering`): component values -> // core values. -import { assert_, NotImplemented } from "./trap.ts"; +import { assert_ } from "./trap.ts"; import { encodeFloatAsI32, encodeFloatAsI64, diff --git a/runtime/src/cabi/store.ts b/runtime/src/cabi/store.ts index 5c97378..c798804 100644 --- a/runtime/src/cabi/store.ts +++ b/runtime/src/cabi/store.ts @@ -1,6 +1,6 @@ // Storing component values into linear memory (definitions.py `## Storing`). -import { assert_, NotImplemented, trapIf } from "./trap.ts"; +import { assert_, trapIf } from "./trap.ts"; import { bytesOf, storeInt, storePtr } from "./memory.ts"; import { tryStoreNumericList } from "./bulk_lists.ts"; import { encodeFloatAsI32, encodeFloatAsI64 } from "./float.ts"; diff --git a/runtime/src/digest/digest.ts b/runtime/src/digest/digest.ts index 1932e06..1cda659 100644 --- a/runtime/src/digest/digest.ts +++ b/runtime/src/digest/digest.ts @@ -215,7 +215,7 @@ function canonExportItem( } function canonFuncType( - plan: WirePlan, + _plan: WirePlan, decl: WireTypeDecl, resourceNames: Map, ): Canon { diff --git a/runtime/src/embedder/instantiate.ts b/runtime/src/embedder/instantiate.ts index c8befee..0efc286 100644 --- a/runtime/src/embedder/instantiate.ts +++ b/runtime/src/embedder/instantiate.ts @@ -41,7 +41,6 @@ import { type ImportLeaf, requiredImports } from "./imports.ts"; import { hostDtorCall } from "../exec/boundary.ts"; import { buildGuestResourceClass, - type ExportWrapper, type GuestResourceSpec, HostResourceRegistry, invalidateWrapper, @@ -59,7 +58,7 @@ import { } from "./values.ts"; import { ImportResolver } from "./version.ts"; import { type ElemCodec, Future, Stream } from "./streams.ts"; -import { markSyncCallable, syncPayloadOf } from "./sync.ts"; +import { markSyncCallable } from "./sync.ts"; /** * Preserve declaration-level suspension/cancellation marks through every @@ -404,59 +403,58 @@ class Facade { // -- the value bridge ------------------------------------------------------ #makeBridge(): ValueBridge { - const self = this; return { - liftOwn(rep, t) { - const b = self.#binding(t.rt.resource); + liftOwn: (rep, t) => { + const b = this.#binding(t.rt.resource); // Host-implemented R: "the host's own instance back; the guest's // handle is gone; no dispose call" (contract 2x4 table). if (b.kind === "host") return b.registry.release(rep); - return makeWrapper(self.#guestClass(b), rep, t.rt.resource, true); + return makeWrapper(this.#guestClass(b), rep, t.rt.resource, true); }, - liftBorrow(rep, t, scope) { - const b = self.#binding(t.rt.resource); + liftBorrow: (rep, t, scope) => { + const b = this.#binding(t.rt.resource); // Host-implemented R: "the host's own instance; borrow scoping is // guest-side bookkeeping" — the mapping is kept. if (b.kind === "host") return b.registry.lookup(rep); - const w = makeWrapper(self.#guestClass(b), rep, t.rt.resource, false); + const w = makeWrapper(this.#guestClass(b), rep, t.rt.resource, false); scope.add(() => invalidateWrapper(w)); return w; }, - lowerOwn(v, t) { - const b = self.#binding(t.rt.resource); + lowerOwn: (v, t) => { + const b = this.#binding(t.rt.resource); if (b.kind === "host") return b.registry.repFor(v); return takeRep(v, t.rt.resource, true, `own<${b.name}>`); }, - lowerBorrow(v, t) { - const b = self.#binding(t.rt.resource); + lowerBorrow: (v, t) => { + const b = this.#binding(t.rt.resource); if (b.kind === "host") { // Each overlapping call retains the rep; the final borrow release // removes only temporary mappings, never a guest-owned registration. const { rep, release } = b.registry.borrowFor(v); - if (self.#lowerScope === null) release(); - else self.#lowerScope.push(release); + if (this.#lowerScope === null) release(); + else this.#lowerScope.push(release); return rep; } // Retain the rep until this call ends; explicit/GC drop must not // destroy it while borrowed (lift_borrow -> Subtask.add_lender). const rep = takeRep(v, t.rt.resource, false, `borrow<${b.name}>`); const release = lendWrapper(v as object); - if (self.#lowerScope === null) { + if (this.#lowerScope === null) { // No enclosing lowering scope (a raw/one-off lowering): the lend // has no observable window, so it must not be left dangling. release(); } else { - self.#lowerScope.push(release); + this.#lowerScope.push(release); } return rep; }, - dropOwn(rep, t) { + dropOwn: (rep, t) => { // resource stream: a lowered `own` the guest will never take (an un-taken // stream element). Destroy it exactly as a guest-side drop would: // host-implemented R runs the instance's [Symbol.dispose] through // the registry; guest-implemented R runs the guest dtor via the // gated path (a host-initiated drop, `caller = None`). - const b = self.#binding(t.rt.resource); + const b = this.#binding(t.rt.resource); if (b.kind === "host") { b.registry.dtor(rep); return; @@ -825,7 +823,6 @@ class Facade { return out; } - // deno-lint-ignore no-explicit-any #buildInterface( id: string, exps: WireExport[], @@ -1014,9 +1011,11 @@ class Facade { } catch (e) { try { release(); - } finally { - throw e; + } catch { + // The original error wins; a secondary failure of the unwind is + // not the story. } + throw e; } finally { this.#lowerScope = outer; } diff --git a/runtime/src/embedder/resources.ts b/runtime/src/embedder/resources.ts index f052408..4704ac1 100644 --- a/runtime/src/embedder/resources.ts +++ b/runtime/src/embedder/resources.ts @@ -349,18 +349,22 @@ export function buildGuestResourceClass( } catch (e) { try { release(); - } finally { - throw e; + } catch { + // The original error wins; a secondary failure of the unwind is + // not the story. } + throw e; } try { release(); } catch (e) { try { if (typeof rep === "number") hostDtorCall(rt, rep); - } finally { - throw e; + } catch { + // The original error wins; a secondary failure of the unwind is + // not the story. } + throw e; } if (rep !== null && typeof rep === "object" && "then" in rep) { throw new TypeError( diff --git a/runtime/src/embedder/streams.ts b/runtime/src/embedder/streams.ts index 7788819..46c3db0 100644 --- a/runtime/src/embedder/streams.ts +++ b/runtime/src/embedder/streams.ts @@ -23,7 +23,7 @@ import { import { CopyResult, dropSharedForTeardown, - ErrorContext as InternalErrorContext, + type ErrorContext as InternalErrorContext, poisonFailureOf, } from "../task/mod.ts"; import { @@ -365,18 +365,17 @@ export class Stream implements ProtocolStream { /** Web-native view: `ReadableStream>`. */ readable(): ReadableStream> { - const self = this; return new ReadableStream>({ - async pull(controller) { - const chunk = await self.read(READ_CHUNK); + pull: async (controller) => { + const chunk = await this.read(READ_CHUNK); if ((chunk as { length: number }).length === 0) { controller.close(); return; } controller.enqueue(chunk); }, - cancel() { - self.drop(); + cancel: () => { + this.drop(); }, }); } diff --git a/runtime/src/exec/boundary.ts b/runtime/src/exec/boundary.ts index 2e146ce..4650fcd 100644 --- a/runtime/src/exec/boundary.ts +++ b/runtime/src/exec/boundary.ts @@ -20,7 +20,7 @@ import { MAX_FLAT_RESULTS, type MemInst, type PtrType, - ResourceTypeInfo, + type ResourceTypeInfo, trap, trapIf, } from "../cabi/mod.ts"; @@ -29,7 +29,7 @@ import { addInstancePoisonedListener, type BlockRequest, type Cancelled, - ComponentInstanceState, + type ComponentInstanceState, driveSyncLift, entryRefusal, EventCode, @@ -42,7 +42,7 @@ import { packSubtaskResult, PendingCapability, realHostCalls, - Store, + type Store, storeQuiescent, Subtask, SubtaskState, diff --git a/runtime/src/exec/executor.ts b/runtime/src/exec/executor.ts index c8fa674..59f1c04 100644 --- a/runtime/src/exec/executor.ts +++ b/runtime/src/exec/executor.ts @@ -9,7 +9,7 @@ // ops (contracts/intrinsics.md) // - component hash verification against plan.component -import type { ComponentValue, FuncType, ValType } from "../cabi/types.ts"; +import type { FuncType, ValType } from "../cabi/types.ts"; import { Trap } from "../cabi/trap.ts"; import { ComponentInstanceState, Store } from "../task/mod.ts"; import { @@ -27,7 +27,6 @@ import { trampolineNeedsSuspension, } from "../jspi/mod.ts"; import { loadPlan, PlanError, resourceIndexOfDefined } from "../plan/loader.ts"; -import { PendingCapability } from "../task/mod.ts"; import type { WireCanonicalOptions, WireCoreDef, diff --git a/runtime/src/intrinsics/async_builtins.ts b/runtime/src/intrinsics/async_builtins.ts index d2d280d..2717dd0 100644 --- a/runtime/src/intrinsics/async_builtins.ts +++ b/runtime/src/intrinsics/async_builtins.ts @@ -37,9 +37,8 @@ import { liftOptionsEqual, needsJspi, Subtask, - SubtaskState, type Task, - Thread, + type Thread, Waitable, WaitableSet, } from "../task/mod.ts"; diff --git a/runtime/src/intrinsics/fact_calls.ts b/runtime/src/intrinsics/fact_calls.ts index 2623fb2..75abc9c 100644 --- a/runtime/src/intrinsics/fact_calls.ts +++ b/runtime/src/intrinsics/fact_calls.ts @@ -56,7 +56,7 @@ import type { CoreValue, FuncType, ValType } from "../cabi/types.ts"; import { type BlockRequest, type Cancelled, - ComponentInstanceState, + type ComponentInstanceState, currentTask, entryRefusal, maybeCurrentTask, @@ -814,12 +814,11 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + // Forward reference: the generator body only runs once `thread` below + // is assigned (spawn returns before the body executes). + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; } diff --git a/runtime/src/intrinsics/mod.ts b/runtime/src/intrinsics/mod.ts index 0774834..26957bb 100644 --- a/runtime/src/intrinsics/mod.ts +++ b/runtime/src/intrinsics/mod.ts @@ -14,12 +14,7 @@ import { trapIf } from "../cabi/trap.ts"; import { assert_ } from "../cabi/trap.ts"; import type { ResourceTableInfo } from "../cabi/types.ts"; import type { ComponentInstanceState } from "../task/mod.ts"; -import { - dbgId, - entryRefusal, - maybeCurrentTask, - maybeCurrentThread, -} from "../task/mod.ts"; +import { dbgId, entryRefusal, maybeCurrentThread } from "../task/mod.ts"; import type { WireTrampoline } from "../plan/format.ts"; import type { CoreFn, ExecutionStats } from "../exec/boundary.ts"; import { UnsupportedFeatureError } from "./errors.ts"; @@ -334,7 +329,6 @@ function declaredInstance( return ctx.componentInstance(instance); } -// deno-lint-ignore no-explicit-any const SCOPE_TRACE = (() => { try { return Deno.env.get("CE_SCOPE_TRACE") === "1"; @@ -347,9 +341,9 @@ const SCOPE_TRACE = (() => { * Brackets belong to the running thread because activations can interleave. * Instantiation-time start functions have no thread and use the executor stack. */ -function syncScopes(ctx: TrampolineContext, site = "?"): any[] { +function syncScopes(ctx: TrampolineContext, site = "?"): SyncCallScope[] { const thread = maybeCurrentThread() as - | { syncCallStack: any[] } + | { syncCallStack: SyncCallScope[] } | undefined; const scopes = thread?.syncCallStack ?? ctx.syncCallStack; if (SCOPE_TRACE) { diff --git a/runtime/src/intrinsics/stream_builtins.ts b/runtime/src/intrinsics/stream_builtins.ts index 06e453f..ec16b08 100644 --- a/runtime/src/intrinsics/stream_builtins.ts +++ b/runtime/src/intrinsics/stream_builtins.ts @@ -28,7 +28,7 @@ import { abandonReasonOf, BUFFER_MAX_LENGTH, type ComponentInstanceState, - CopyEnd, + type CopyEnd, CopyResult, CopyState, currentInstance, diff --git a/runtime/src/task/scheduler.ts b/runtime/src/task/scheduler.ts index eb5f2ae..aaa008d 100644 --- a/runtime/src/task/scheduler.ts +++ b/runtime/src/task/scheduler.ts @@ -489,7 +489,6 @@ export function maybeCurrentThread(): CurrentThreadLike | undefined { * the brackets and claims. In definitions.py `canon_context_get` and * `canon_context_set`, identity comes directly from `current_thread`. */ -// deno-lint-ignore no-explicit-any export function currentThreadForInstance( inst: unknown, ): T { diff --git a/runtime/src/task/streams.ts b/runtime/src/task/streams.ts index 0a0d13c..67acf92 100644 --- a/runtime/src/task/streams.ts +++ b/runtime/src/task/streams.ts @@ -10,7 +10,7 @@ import { defineBrand, ERROR_CONTEXT } from "@polyengine/protocol"; import { assert_, Trap, trapIf } from "../cabi/trap.ts"; -import { LiftLowerContext } from "../cabi/context.ts"; +import type { LiftLowerContext } from "../cabi/context.ts"; import { bytesOf } from "../cabi/memory.ts"; import { loadListFromValidRange } from "../cabi/load.ts"; import { storeListIntoValidRange } from "../cabi/store.ts"; diff --git a/runtime/tests/async_builtins_test.ts b/runtime/tests/async_builtins_test.ts index 57df1b6..b863ccc 100644 --- a/runtime/tests/async_builtins_test.ts +++ b/runtime/tests/async_builtins_test.ts @@ -20,6 +20,7 @@ import { createStreamNew, createStreamRead, createStreamWrite, + type StreamTrampolineContext, } from "../src/intrinsics/stream_builtins.ts"; import { createLiftedFunction, @@ -348,16 +349,14 @@ Deno.test("stream.cancel-write supersedes an undelivered COMPLETED", () => { // deno-lint-ignore no-explicit-any const newStream = createStreamNew({ streamTable: 0 }, ctx as any, inst); - // deno-lint-ignore no-explicit-any const write = createStreamWrite( { streamTable: 0, options: 0 }, - ctx as any, + ctx as unknown as StreamTrampolineContext, inst, ); - // deno-lint-ignore no-explicit-any const read = createStreamRead( { streamTable: 0, options: 0 }, - ctx as any, + ctx as unknown as StreamTrampolineContext, inst, ); const cancelWrite = createStreamCancelWrite( diff --git a/runtime/tests/builtin_index_normalization_test.ts b/runtime/tests/builtin_index_normalization_test.ts index 15a8abe..e313b21 100644 --- a/runtime/tests/builtin_index_normalization_test.ts +++ b/runtime/tests/builtin_index_normalization_test.ts @@ -43,7 +43,6 @@ import { Store, Task, Thread, - WaitableSet, } from "../src/task/mod.ts"; import type { ResolvedOptions } from "../src/exec/boundary.ts"; diff --git a/runtime/tests/conventions/error_context_test.ts b/runtime/tests/conventions/error_context_test.ts index 371be9f..91562d9 100644 --- a/runtime/tests/conventions/error_context_test.ts +++ b/runtime/tests/conventions/error_context_test.ts @@ -102,7 +102,7 @@ Deno.test({ name: "conventions/g: isErrorContext accepts a hand-rolled carrier, rejects a husk", fn: async () => { - await transcript("g-error-context-predicate", async (t) => { + await transcript("g-error-context-predicate", (t) => { // The vocabulary claim on its own: recognition is brand + string // `message`, in any copy, hand-rolled or not. t.note("hand-rolled", { @@ -113,6 +113,7 @@ Deno.test({ husk[Symbol.for(ERROR_CONTEXT_KEY)] = true; t.note("branded-non-string-message", { classified: classify(husk) }); t.note("unbranded", { classified: classify({ message: "m" }) }); + return Promise.resolve(); }); }, }); diff --git a/runtime/tests/conventions/errors_test.ts b/runtime/tests/conventions/errors_test.ts index ffb137f..5aea922 100644 --- a/runtime/tests/conventions/errors_test.ts +++ b/runtime/tests/conventions/errors_test.ts @@ -17,7 +17,7 @@ // predicate. Trap MESSAGE text is diagnostic, not API — an engine-worded trap // (a raw `unreachable`) is recorded by brand alone (see support.ts). -import { guest, haveFixture, instantiateFixture, testdata } from "./harness.ts"; +import { guest, haveFixture, instantiateFixture } from "./harness.ts"; import { transcript } from "./support.ts"; import { classify, ComponentException } from "./probe.ts"; import { handRolledException } from "./probe_zero_import.ts"; @@ -143,7 +143,7 @@ Deno.test({ name: "conventions/e: predicates recognize a hand-rolled exception, either copy", fn: async () => { - await transcript("e-brand-recognition", async (t) => { + await transcript("e-brand-recognition", (t) => { // No engine involved: the vocabulary claim itself. A hand-rolled brand // and the canonical class are the same thing to every predicate, because // the brand is a `Symbol.for` registry symbol. @@ -157,6 +157,7 @@ Deno.test({ // A payloadless err: `payload` is `undefined`, and the property is // PRESENT (the empty-side spelling), which normalize() records. t.note("payloadless", { value: new ComponentException(undefined) }); + return Promise.resolve(); }); }, }); diff --git a/runtime/tests/embedder/future_result_test.ts b/runtime/tests/embedder/future_result_test.ts index db40a48..0ebb023 100644 --- a/runtime/tests/embedder/future_result_test.ts +++ b/runtime/tests/embedder/future_result_test.ts @@ -16,14 +16,14 @@ import { caught, guest, haveFixture, instantiateFixture } from "./support.ts"; import { Future, lowerFutureSource, - Stream, + type Stream, } from "../../src/embedder/streams.ts"; import { hostFuture, hostFutureFor } from "../../src/exec/host_streams.ts"; -import { HostResourceRegistry } from "../../src/embedder/resources.ts"; +import type { HostResourceRegistry } from "../../src/embedder/resources.ts"; import { INTERNAL_HOST_REGISTRIES } from "../../src/embedder/instantiate.ts"; import { sync } from "../../src/embedder/sync.ts"; import { StreamProducerError, Trap } from "@polyengine/protocol"; -import { SharedFutureImpl } from "../../src/task/mod.ts"; +import type { SharedFutureImpl } from "../../src/task/mod.ts"; const turn = () => new Promise((resolve) => setTimeout(resolve, 0)); const ownFixture = "runtime/tests/embedder/future-own.wasm"; @@ -218,8 +218,8 @@ for (const synchronous of [false, true]) { toHost: (v) => v as number, fromHost: (v) => v, }); - let registry: HostResourceRegistry; - let rep: number; + // Forward reference: the closure runs later, after `registry`/`rep` + // below are filled in. const c = await instantiateFixture(cleanupFixture, { r: R, next: () => future, @@ -228,12 +228,12 @@ for (const synchronous of [false, true]) { if (callFails) throw primary; }, }); - registry = + const registry = (c as unknown as Record>)[ INTERNAL_HOST_REGISTRIES ].get(0)!; const cell = new R(); - rep = registry.repFor(cell); + const rep = registry.repFor(cell); let observed: unknown; try { await (synchronous ? sync(c.exports.run)(cell) : c.exports.run(cell)); diff --git a/runtime/tests/embedder/host_imports_test.ts b/runtime/tests/embedder/host_imports_test.ts index b482ae6..f3e61ac 100644 --- a/runtime/tests/embedder/host_imports_test.ts +++ b/runtime/tests/embedder/host_imports_test.ts @@ -358,8 +358,8 @@ for (const mode of ["constructor", "promise", "sync"] as const) { throw boom; } } - let registry: HostResourceRegistry; - let rep: number; + // Forward reference: the closure runs later, after `registry`/`rep` + // below are filled in. const c = await instantiateFixture(overlapFixture, { "host:api/res": { R, @@ -369,12 +369,12 @@ for (const mode of ["constructor", "promise", "sync"] as const) { }, }, }); - registry = + const registry = (c as unknown as Record>)[ INTERNAL_HOST_REGISTRIES ].get(0)!; const cell = new R(); - rep = registry.repFor(cell); + const rep = registry.repFor(cell); const e = await caught(() => mode === "constructor" ? new c.exports.Ticket(cell) @@ -405,8 +405,8 @@ for (const mode of ["constructor", "promise", "sync"] as const) { throw new Error("secondary disposal"); } } - let registry: HostResourceRegistry; - let rep: number; + // Forward reference: the closure runs later, after `registry`/`rep` + // below are filled in. const c = await instantiateFixture(overlapFixture, { "host:api/res": { R, @@ -416,12 +416,12 @@ for (const mode of ["constructor", "promise", "sync"] as const) { }, }, }); - registry = + const registry = (c as unknown as Record>)[ INTERNAL_HOST_REGISTRIES ].get(0)!; const cell = new R(); - rep = registry.repFor(cell); + const rep = registry.repFor(cell); const e = await caught(() => mode === "constructor" ? new c.exports.Ticket(cell) @@ -617,7 +617,7 @@ Deno.test({ symbol, Map >)[INTERNAL_HOST_REGISTRIES].get(0)!; - using ticket = new c.exports.Ticket(cell); + using _ticket = new c.exports.Ticket(cell); assertEq(seen === cell, true); assertEq(registry.liveCount, 0); }, diff --git a/runtime/tests/embedder/platform_class_test.ts b/runtime/tests/embedder/platform_class_test.ts index e7a6dd5..5390429 100644 --- a/runtime/tests/embedder/platform_class_test.ts +++ b/runtime/tests/embedder/platform_class_test.ts @@ -25,7 +25,7 @@ import { assertEq } from "../support/asserts.ts"; import { caught, haveFixture, instantiateFixture } from "./support.ts"; -import { ComponentException, isTrap, Trap } from "@polyengine/protocol"; +import { ComponentException, isTrap } from "@polyengine/protocol"; const FIXTURE = "runtime/tests/embedder/platform-class.wasm"; const ready = await haveFixture(FIXTURE); diff --git a/runtime/tests/entry_deferral_test.ts b/runtime/tests/entry_deferral_test.ts index d782d02..fdd2692 100644 --- a/runtime/tests/entry_deferral_test.ts +++ b/runtime/tests/entry_deferral_test.ts @@ -79,13 +79,10 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; } diff --git a/runtime/tests/fact_call_test.ts b/runtime/tests/fact_call_test.ts index a1565ce..8433fc1 100644 --- a/runtime/tests/fact_call_test.ts +++ b/runtime/tests/fact_call_test.ts @@ -17,9 +17,13 @@ import { assertEq } from "./support/asserts.ts"; import { createAsyncStartCall, createPrepareCall, + type FactCallContext, type PreparedCall, } from "../src/intrinsics/fact_calls.ts"; -import { createTaskReturn } from "../src/intrinsics/async_builtins.ts"; +import { + type AsyncTrampolineContext, + createTaskReturn, +} from "../src/intrinsics/async_builtins.ts"; import { newStats, type ResolvedOptions } from "../src/exec/boundary.ts"; import { ComponentInstanceState, @@ -94,12 +98,13 @@ function runPrepared(input: { ? input.calleeResults[0] : input.calleeResults; - // deno-lint-ignore no-explicit-any - const prep = createPrepareCall({ memory: null }, ctx as any); - // deno-lint-ignore no-explicit-any + const prep = createPrepareCall( + { memory: null }, + ctx as unknown as FactCallContext, + ); const startCall = createAsyncStartCall( { callback: null, postReturn: null }, - ctx as any, + ctx as unknown as FactCallContext, ); prep( @@ -214,12 +219,11 @@ Deno.test("FACT: task.return preserves float lanes on the passthrough", () => { // plan v3: `results` = raw wasmtime TypeTupleIndex, `resultType` = the // interned plan.types entry (here: the empty tuple, type 0). { results: 0, resultType: 0, options: 0 }, - // deno-lint-ignore no-explicit-any { componentInstance: () => inst, options: () => opts, resultTypes: () => [], - } as any, + } as unknown as AsyncTrampolineContext, ); const thread = new Thread(task, (function* () {})()); pushCurrentThread(thread); diff --git a/runtime/tests/host_import_cancel_test.ts b/runtime/tests/host_import_cancel_test.ts index b275e97..5b5b6bf 100644 --- a/runtime/tests/host_import_cancel_test.ts +++ b/runtime/tests/host_import_cancel_test.ts @@ -39,7 +39,7 @@ import { popCurrentThread, pushCurrentThread, Store, - Subtask, + type Subtask, SubtaskState, Task, type TaskOptions, diff --git a/runtime/tests/integration/e2e_async_test.ts b/runtime/tests/integration/e2e_async_test.ts index 437c7ab..1e969be 100644 --- a/runtime/tests/integration/e2e_async_test.ts +++ b/runtime/tests/integration/e2e_async_test.ts @@ -18,8 +18,7 @@ import { assertEq } from "../support/asserts.ts"; import { Translator } from "../../src/shim/mod.ts"; import { instantiateComponent } from "../../src/exec/mod.ts"; -import { PendingCapability } from "../../src/task/mod.ts"; -import { AssertionError, NotImplemented, Trap } from "../../src/cabi/mod.ts"; +import { AssertionError } from "../../src/cabi/mod.ts"; function assert(cond: boolean, msg: string): asserts cond { if (!cond) throw new Error(`assertion failed: ${msg}`); diff --git a/runtime/tests/park_state_settle_test.ts b/runtime/tests/park_state_settle_test.ts index 6d2679c..538b725 100644 --- a/runtime/tests/park_state_settle_test.ts +++ b/runtime/tests/park_state_settle_test.ts @@ -53,7 +53,7 @@ import type { SuspensionPoint } from "../src/jspi/mod.ts"; import { canonResourceDrop, canonResourceNew, - ResourceHandle, + type ResourceHandle, ResourceTableInfo, ResourceTypeInfo, } from "../src/cabi/mod.ts"; diff --git a/runtime/tests/resource_identity_test.ts b/runtime/tests/resource_identity_test.ts index 6842a27..47a99b9 100644 --- a/runtime/tests/resource_identity_test.ts +++ b/runtime/tests/resource_identity_test.ts @@ -6,7 +6,7 @@ import { canonResourceNew, canonResourceRep, LiftLowerContext, - ResourceHandle, + type ResourceHandle, ResourceTableInfo, ResourceTypeInfo, Trap, @@ -33,7 +33,7 @@ import { } from "../src/exec/boundary.ts"; import { ComponentInstanceState, - CopyEnd, + type CopyEnd, CopyState, popCurrentThread, pushCurrentThread, diff --git a/runtime/tests/resource_lender_park_settle_test.ts b/runtime/tests/resource_lender_park_settle_test.ts index 4cdf8b4..a4ed2ad 100644 --- a/runtime/tests/resource_lender_park_settle_test.ts +++ b/runtime/tests/resource_lender_park_settle_test.ts @@ -33,6 +33,7 @@ import { createAsyncStartCall, createPrepareCall, createSyncStartCall, + type FactCallContext, type PreparedCall, } from "../src/intrinsics/fact_calls.ts"; import type { FactStartScope } from "../src/intrinsics/mod.ts"; @@ -46,7 +47,7 @@ import type { SuspensionPoint } from "../src/jspi/mod.ts"; import { canonResourceDrop, canonResourceNew, - ResourceHandle, + type ResourceHandle, ResourceTableInfo, ResourceTypeInfo, } from "../src/cabi/mod.ts"; @@ -130,15 +131,18 @@ function mkHarness(): Harness { }; const return_ = () => undefined as unknown as CoreValue; - // deno-lint-ignore no-explicit-any - const prep = createPrepareCall({ memory: null }, ctx as any); + const prep = createPrepareCall( + { memory: null }, + ctx as unknown as FactCallContext, + ); const startCall = kind === "sync" - // deno-lint-ignore no-explicit-any - ? createSyncStartCall({ callback: null }, ctx as any) - // deno-lint-ignore no-explicit-any + ? createSyncStartCall( + { callback: null }, + ctx as unknown as FactCallContext, + ) : createAsyncStartCall( { callback: null, postReturn: null }, - ctx as any, + ctx as unknown as FactCallContext, ); prep( diff --git a/runtime/tests/resource_lender_unwind_test.ts b/runtime/tests/resource_lender_unwind_test.ts index 471714b..45528d7 100644 --- a/runtime/tests/resource_lender_unwind_test.ts +++ b/runtime/tests/resource_lender_unwind_test.ts @@ -24,7 +24,7 @@ import { NeedsJspi } from "../src/task/scheduler.ts"; import { canonResourceDrop, canonResourceNew, - ResourceHandle, + type ResourceHandle, ResourceTableInfo, ResourceTypeInfo, } from "../src/cabi/mod.ts"; diff --git a/runtime/tests/settled_deferral_test.ts b/runtime/tests/settled_deferral_test.ts index 96da05d..84be3bb 100644 --- a/runtime/tests/settled_deferral_test.ts +++ b/runtime/tests/settled_deferral_test.ts @@ -34,13 +34,12 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + // Forward reference: the generator body only runs once `thread` below + // is assigned (spawn returns before the body executes). + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; } diff --git a/runtime/tests/settlement_pump_test.ts b/runtime/tests/settlement_pump_test.ts index e328a39..0c0a52d 100644 --- a/runtime/tests/settlement_pump_test.ts +++ b/runtime/tests/settlement_pump_test.ts @@ -24,10 +24,6 @@ import { assertEq } from "./support/asserts.ts"; import { driveStoreAsync } from "../src/exec/mod.ts"; import { markHostActivityArm, Store } from "../src/task/mod.ts"; -function assert(cond: boolean, msg: string): asserts cond { - if (!cond) throw new Error(`assertion failed: ${msg}`); -} - /** The slice of `ComponentInstance` that `Store.tick` touches. */ function fakeInst() { return {}; diff --git a/runtime/tests/stale_cancellable_flag_test.ts b/runtime/tests/stale_cancellable_flag_test.ts index eda2f2d..536aa25 100644 --- a/runtime/tests/stale_cancellable_flag_test.ts +++ b/runtime/tests/stale_cancellable_flag_test.ts @@ -33,13 +33,12 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + // Forward reference: the generator body only runs once `thread` below + // is assigned (spawn returns before the body executes). + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; } diff --git a/runtime/tests/streams_teardown_test.ts b/runtime/tests/streams_teardown_test.ts index 0cff7fb..d0ed4ad 100644 --- a/runtime/tests/streams_teardown_test.ts +++ b/runtime/tests/streams_teardown_test.ts @@ -736,7 +736,7 @@ Deno.test("#100: a host peer parked on a poisoned guest's end is still notified" for (const future of [false, true]) { for (const writable of [false, true]) { - Deno.test(`removed busy ${future ? "future" : "stream"} ${writable ? "writer" : "reader"} cannot copy stale guest bytes`, async () => { + Deno.test(`removed busy ${future ? "future" : "stream"} ${writable ? "writer" : "reader"} cannot copy stale guest bytes`, () => { const inst = new ComponentInstanceState(0, new Store()); const { memory, view } = mkMemory(); const u8 = { kind: "u8" } as const; diff --git a/runtime/tests/suspension_point_pending_cancel_test.ts b/runtime/tests/suspension_point_pending_cancel_test.ts index a2a355b..ba50aa6 100644 --- a/runtime/tests/suspension_point_pending_cancel_test.ts +++ b/runtime/tests/suspension_point_pending_cancel_test.ts @@ -45,13 +45,12 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + // Forward reference: the generator body only runs once `thread` below + // is assigned (spawn returns before the body executes). + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; } diff --git a/runtime/tests/task_test.ts b/runtime/tests/task_test.ts index 35213cc..cf3de9e 100644 --- a/runtime/tests/task_test.ts +++ b/runtime/tests/task_test.ts @@ -85,13 +85,12 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + // Forward reference: the generator body only runs once `thread` below + // is assigned (spawn returns before the body executes). + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; } diff --git a/runtime/tests/wait_until_pending_cancel_test.ts b/runtime/tests/wait_until_pending_cancel_test.ts index b2e4351..294ba4d 100644 --- a/runtime/tests/wait_until_pending_cancel_test.ts +++ b/runtime/tests/wait_until_pending_cancel_test.ts @@ -42,13 +42,12 @@ function spawn( task: Task, body: (t: Thread) => Generator, ): Thread { - let thread!: Thread; - thread = new Thread( - task, - (function* (): Generator { - yield* body(thread); - })(), - ); + // Forward reference: the generator body only runs once `thread` below + // is assigned (spawn returns before the body executes). + function* threadBody(): Generator { + yield* body(thread); + } + const thread: Thread = new Thread(task, threadBody()); return thread; }