Skip to content

Commit 0e2e402

Browse files
hyperpolymathclaude
andcommitted
feat(affine-vscode): implement withProgressNotification runtime adapter
stdlib/Vscode.affine:307 declares `withProgressNotification(title, work: fn(Unit) -> Thenable) -> Thenable / Async`, but packages/affine-vscode/mod.js had no runtime impl — calling it from the wasm/Node backend faulted (undefined extern). Surfaced by the first #205 consumer (rsr-certifier extension rewire, standards#123), which had to omit progress UI and document the gap. Adds the impl following the established async-extern convention exactly: - `work` is the #199 closure (`fn(Unit) -> Thenable`); invoking it via wrapHandler returns the guest's Thenable *handle*, resolved through the shared handle table. - The overall progress Thenable is `reg`-ed so the guest observes completion with thenableThen / thenableResultJson, identical to httpPostJson (#210). - Failures settle as `{ __error }` — the same reject shape thenableThen / httpPostJson use, so guests branch to a fallback uniformly. - Graceful degradation: if the host has no `withProgress` (non-VS Code / test runner), the work still runs; only the progress chrome is skipped (mirrors httpPostJson's fetch-unavailable stance). Pure adapter addition — no stdlib/compiler change (the extern was already declared). Node syntax-checked; full dune gate green (257/257), zero regression. Closes #212 Refs #199 #205 #210 #211 ; consumer hyperpolymath/standards#123 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d620b41 commit 0e2e402

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

packages/affine-vscode/mod.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,37 @@ module.exports = function makeVscodeBindings(vscode, lcModule, hostShim) {
405405
return reg("");
406406
}
407407
},
408+
409+
// `withProgressNotification(title, work)` (issue #212) — wrap a guest
410+
// async unit of work in a VS Code progress notification. `work` is the
411+
// #199 closure (`fn(Unit) -> Thenable`); invoking it returns the guest's
412+
// Thenable *handle*, which we resolve through the shared handle table.
413+
// We register the overall progress Thenable so the guest observes
414+
// completion with thenableThen / thenableResultJson, identical to
415+
// httpPostJson. If the host has no withProgress (non-VS Code / test
416+
// runner) the work still runs — only the progress chrome is skipped.
417+
// Failures settle as { __error } (the established reject shape).
418+
withProgressNotification: (titlePtr, workPtr) => {
419+
const title = readString(titlePtr);
420+
const work = wrapHandler(workPtr);
421+
const runWork = () => {
422+
const h = work();
423+
const inner = (typeof h === "number") ? get(h) : h;
424+
return Promise.resolve(inner);
425+
};
426+
const canProgress =
427+
typeof vscode.window.withProgress === "function" &&
428+
vscode.ProgressLocation;
429+
const result = canProgress
430+
? vscode.window.withProgress(
431+
{ location: vscode.ProgressLocation.Notification, title },
432+
() => runWork()
433+
)
434+
: runWork();
435+
return reg(
436+
Promise.resolve(result).catch((err) => ({ __error: String(err) }))
437+
);
438+
},
408439
};
409440

410441
const VscodeLanguageClient = {

0 commit comments

Comments
 (0)