Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/affine-vscode/mod.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ module.exports = function makeVscodeBindings(vscode, lcModule, hostShim) {
const reg = (obj) => hostShim._registerHandle(obj);
const get = (h) => hostShim._getHandle(h);
const getInstance = () => hostShim._instance;
// Settled host-Thenable values, keyed by Thenable handle (issue #205).
const __thenableResults = new Map();

// ── String marshalling ─────────────────────────────────────────────
// AffineScript's WASM 1.0 codegen stores string literals at the offset
Expand Down Expand Up @@ -333,6 +335,34 @@ module.exports = function makeVscodeBindings(vscode, lcModule, hostShim) {
const ctx = get(ctxHandle);
return reg(ctx ? ctx.asAbsolutePath(readString(relPtr)) : "");
},

// ── Thenable resolution (issue #205) ───────────────────────────
// The wasm guest cannot await; these let it observe a settled host
// Thenable. thenableThen registers the guest closure (reusing the
// #199 closure-pointer marshalling via wrapHandler) and stores the
// settled value keyed by the Thenable handle; thenableResultJson
// returns it JSON-encoded (same reg(string) return convention as
// every other `-> String` extern).
thenableThen: (tHandle, onSettlePtr) => {
const thenable = get(tHandle);
const cb = wrapHandler(onSettlePtr);
if (!thenable || typeof thenable.then !== "function") {
return reg({ dispose() {} });
}
Promise.resolve(thenable).then(
(val) => { __thenableResults.set(tHandle, val); try { cb(); } catch (_e) {} },
(err) => {
__thenableResults.set(tHandle, { __error: String(err) });
try { cb(); } catch (_e) {}
}
);
return reg({ dispose() {} });
},
thenableResultJson: (tHandle) => {
if (!__thenableResults.has(tHandle)) return reg("");
try { return reg(JSON.stringify(__thenableResults.get(tHandle))); }
catch (_e) { return reg(""); }
},
};

const VscodeLanguageClient = {
Expand Down
17 changes: 17 additions & 0 deletions stdlib/Vscode.affine
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,20 @@ pub extern fn extensionAbsolutePath(ctx: ExtensionContext, rel_path: String) ->
/// explicit `Unit` param avoids the zero-param-fn return-type collapse).
/// Returns the progress Thenable.
pub extern fn withProgressNotification(title: String, work: fn(Unit) -> Thenable) -> Thenable / Async;

// ── Thenable resolution (issue #205) ─────────────────────────────────
//
// The source-to-source backend can `await` a Thenable directly; the
// wasm/Node backend cannot, so these primitives let a wasm guest
// observe a settled host Thenable. `thenableThen` registers a guest
// callback (the #199 function-value ABI — the host re-enters it when
// the Thenable settles); `thenableResultJson` reads the settled payload
// JSON-encoded once the callback has fired.

/// Run `on_settle` when `t` resolves. `on_settle` is a function value
/// (#199); the host invokes it after settlement. Returns a Disposable.
pub extern fn thenableThen(t: Thenable, on_settle: fn(Unit) -> Int) -> Disposable / Async;

/// The resolved value of `t`, JSON-encoded. Empty string until `t` has
/// settled (i.e. until the `thenableThen` callback has fired).
pub extern fn thenableResultJson(t: Thenable) -> String;
Loading