diff --git a/common/space_lua/runtime.ts b/common/space_lua/runtime.ts index 1d194037..234efbdf 100644 --- a/common/space_lua/runtime.ts +++ b/common/space_lua/runtime.ts @@ -18,7 +18,7 @@ export type JSValue = any; export interface ILuaFunction { call(sf: LuaStackFrame, ...args: LuaValue[]): Promise | LuaValue; - toString(): string; + asString(): string; } export interface ILuaSettable { @@ -196,10 +196,14 @@ export class LuaFunction implements ILuaFunction { return this.callWithArgs(resolvedArgs, env, sf); } - toString(): string { + asString(): string { return ``; } + toString(): string { + return this.asString(); + } + private callWithArgs( args: LuaValue[], env: LuaEnv, @@ -271,9 +275,13 @@ export class LuaNativeJSFunction implements ILuaFunction { } } - toString(): string { + asString(): string { return ``; } + + toString(): string { + return this.asString(); + } } export class LuaBuiltinFunction implements ILuaFunction { @@ -287,9 +295,13 @@ export class LuaBuiltinFunction implements ILuaFunction { return this.fn(sf, ...args); } - toString(): string { + asString(): string { return ``; } + + toString(): string { + return this.asString(); + } } export class LuaTable implements ILuaSettable, ILuaGettable { @@ -730,6 +742,10 @@ export function luaToString( visited.add(value); return value.toStringAsync(); } + if (value.asString) { + visited.add(value); + return value.asString(); + } if (value instanceof LuaFunction) { // Don't recurse into the function body, just show the function signature return ``; diff --git a/common/syscalls/lua.ts b/common/syscalls/lua.ts index 81087f9c..d83831ce 100644 --- a/common/syscalls/lua.ts +++ b/common/syscalls/lua.ts @@ -2,8 +2,13 @@ import type { SysCallMapping } from "$lib/plugos/system.ts"; import { evalExpression } from "$common/space_lua/eval.ts"; import { parse, parseExpressionString } from "../space_lua/parse.ts"; import type { CommonSystem } from "$common/common_system.ts"; -import { LuaStackFrame, luaValueToJS } from "$common/space_lua/runtime.ts"; +import { + LuaStackFrame, + luaToString, + luaValueToJS, +} from "$common/space_lua/runtime.ts"; import { buildThreadLocalEnv } from "$common/space_lua_api.ts"; +import { isSendable } from "$lib/plugos/util.ts"; export function luaSyscalls(commonSystem: CommonSystem): SysCallMapping { return { @@ -24,9 +29,17 @@ export function luaSyscalls(commonSystem: CommonSystem): SysCallMapping { commonSystem.spaceLuaEnv.env, ); const sf = new LuaStackFrame(env, null); - return luaValueToJS( - evalExpression(ast, commonSystem.spaceLuaEnv.env, sf), - ); + const result = evalExpression(ast, commonSystem.spaceLuaEnv.env, sf); + if (isSendable(result)) { + return luaValueToJS(result); + } else { + // This may evaluate to e.g. a function, which is not sendable, in this case we'll console.warn and return a stringified version of the result + console.warn( + "Lua eval result is not sendable, returning stringified version", + result, + ); + return luaToString(result); + } } catch (e: any) { console.error("Lua eval error: ", e.message, e.sf?.astCtx); throw e; diff --git a/lib/plugos/util.ts b/lib/plugos/util.ts new file mode 100644 index 00000000..3352cccb --- /dev/null +++ b/lib/plugos/util.ts @@ -0,0 +1,14 @@ +/** + * Checks if an object is sendable across the plugos worker boundary. + * + * @param o - The object to check. + * @returns `true` if the object is sendable, `false` otherwise. + */ +export function isSendable(o: any): boolean { + try { + structuredClone(o); + return true; + } catch { + return false; + } +} diff --git a/plugs/markdown/api.ts b/plugs/markdown/api.ts index 2b6685d9..39223a71 100644 --- a/plugs/markdown/api.ts +++ b/plugs/markdown/api.ts @@ -105,10 +105,9 @@ export async function expandCodeWidgets( ); } } else if (n.type === "LuaDirective") { - const expr: LuaExpression | null = findNodeOfType( - n, - "LuaExpressionDirective", - ) as LuaExpression | null; + const expr = findNodeOfType(n, "LuaExpressionDirective") as + | LuaExpression + | null; if (!expr) { return; } diff --git a/web/cm_plugins/lua_widget.ts b/web/cm_plugins/lua_widget.ts index 4a114a39..8c37ce02 100644 --- a/web/cm_plugins/lua_widget.ts +++ b/web/cm_plugins/lua_widget.ts @@ -25,8 +25,6 @@ export type LuaWidgetContent = { markdown?: string; // CSS classes for wrapper cssClasses?: string[]; - // Index objects - objects?: ObjectValue[]; display?: "block" | "inline"; } | string;