pull/1219/merge
Zef Hemel 2025-02-08 16:51:31 +01:00
parent 2978f4a8d6
commit 9317d143b3
5 changed files with 54 additions and 14 deletions

View File

@ -18,7 +18,7 @@ export type JSValue = any;
export interface ILuaFunction {
call(sf: LuaStackFrame, ...args: LuaValue[]): Promise<LuaValue> | 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 `<lua function(${this.body.parameters.join(", ")})>`;
}
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 `<native js function: ${this.fn.name}>`;
}
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 `<builtin lua function>`;
}
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 `<lua-function (${value.body.parameters.join(", ")})>`;

View File

@ -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;

14
lib/plugos/util.ts Normal file
View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -25,8 +25,6 @@ export type LuaWidgetContent = {
markdown?: string;
// CSS classes for wrapper
cssClasses?: string[];
// Index objects
objects?: ObjectValue<any>[];
display?: "block" | "inline";
} | string;