silverbullet/common/space_lua_api.ts

96 lines
2.6 KiB
TypeScript
Raw Normal View History

2024-10-11 21:34:27 +08:00
import { luaBuildStandardEnv } from "$common/space_lua/stdlib.ts";
import { parsePageRef } from "@silverbulletmd/silverbullet/lib/page_ref";
import {
LuaEnv,
LuaNativeJSFunction,
2025-02-06 15:34:23 +08:00
type LuaRuntimeError,
2024-10-20 21:06:23 +08:00
LuaStackFrame,
2024-10-11 21:34:27 +08:00
LuaTable,
} from "$common/space_lua/runtime.ts";
import type { System } from "$lib/plugos/system.ts";
export function buildLuaEnv(system: System<any>) {
2024-10-11 21:34:27 +08:00
const env = new LuaEnv(luaBuildStandardEnv());
2024-10-13 21:14:22 +08:00
// Expose all syscalls to Lua
exposeSyscalls(env, system);
return env;
}
function exposeSyscalls(env: LuaEnv, system: System<any>) {
2024-10-11 21:34:27 +08:00
// Expose all syscalls to Lua
2025-01-15 03:26:47 +08:00
// Except...
const blacklist = ["template", "shell"];
2024-10-20 21:06:23 +08:00
const nativeFs = new LuaStackFrame(env, null);
2024-10-11 21:34:27 +08:00
for (const syscallName of system.registeredSyscalls.keys()) {
if (blacklist.includes(syscallName)) {
2025-01-15 03:26:47 +08:00
continue;
}
2024-10-11 21:34:27 +08:00
const [ns, fn] = syscallName.split(".");
2024-10-20 21:06:23 +08:00
if (!env.has(ns)) {
env.set(ns, new LuaTable(), nativeFs);
2024-10-11 21:34:27 +08:00
}
const luaFn = new LuaNativeJSFunction((...args) => {
return system.localSyscall(syscallName, args);
});
2024-10-20 21:06:23 +08:00
env.get(ns, nativeFs).set(fn, luaFn, nativeFs);
2024-10-11 21:34:27 +08:00
}
2024-10-13 21:14:22 +08:00
}
2024-10-11 21:34:27 +08:00
2025-01-23 03:26:37 +08:00
export async function buildThreadLocalEnv(
system: System<any>,
globalEnv: LuaEnv,
) {
2025-01-09 00:09:09 +08:00
const tl = new LuaEnv();
2025-01-23 03:26:37 +08:00
if (system.registeredSyscalls.has("editor.getCurrentPageMeta")) {
const currentPageMeta = await system.localSyscall(
"editor.getCurrentPageMeta",
[],
);
if (currentPageMeta) {
tl.setLocal("currentPage", currentPageMeta);
} else {
tl.setLocal("currentPage", {
name: await system.localSyscall("editor.getCurrentPage", []),
});
}
}
2025-01-09 18:45:15 +08:00
tl.setLocal("_GLOBAL", globalEnv);
2025-01-18 01:32:13 +08:00
return Promise.resolve(tl);
2025-01-09 00:09:09 +08:00
}
2025-02-06 15:34:23 +08:00
export async function handleLuaError(e: LuaRuntimeError, system: System<any>) {
2024-10-13 21:14:22 +08:00
console.error(
"Lua eval exception",
e.message,
e.sf?.astCtx,
2024-10-13 21:14:22 +08:00
);
if (e.sf?.astCtx && e.sf.astCtx.ref) {
2024-10-13 21:14:22 +08:00
// We got an error and actually know where it came from, let's navigate there to help debugging
2025-02-06 15:34:23 +08:00
const pageRef = parsePageRef(e.sf.astCtx.ref);
2024-10-13 21:14:22 +08:00
await system.localSyscall(
"editor.flashNotification",
[
`Lua error: ${e.message}`,
"error",
],
);
await system.localSyscall(
"editor.flashNotification",
[
`Navigating to the place in the code where this error occurred in ${pageRef.page}`,
"info",
],
);
await system.localSyscall("editor.navigate", [
{
page: pageRef.page,
2025-02-06 15:34:23 +08:00
pos: (typeof pageRef.pos === "number" ? pageRef.pos : 0) +
(e.sf.astCtx?.from ?? 0) +
2024-10-13 21:14:22 +08:00
"```space-lua\n".length,
},
]);
}
2024-10-11 21:34:27 +08:00
}