diff options
| author | t <t@tjp.lol> | 2026-06-10 09:46:00 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-06-10 09:55:05 -0600 |
| commit | 9bf1d800f2a24ed71221c64370c98ee8d907314b (patch) | |
| tree | d1b77ac9140e57ba523e97a4b815475ddba2c04e /src/lua_runtime.zig | |
| parent | 938db5f476184b2d4f613e04cce60a5191581d7f (diff) | |
expose `panto` to extensions as a require()able module, not a global
Diffstat (limited to 'src/lua_runtime.zig')
| -rw-r--r-- | src/lua_runtime.zig | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/lua_runtime.zig b/src/lua_runtime.zig index 797b97b..e26d017 100644 --- a/src/lua_runtime.zig +++ b/src/lua_runtime.zig @@ -263,7 +263,7 @@ pub const LuaRuntime = struct { // so its return value naturally lands above it; calling pcall then // consumes both in the right order. const L = self.L; - _ = c.lua_getglobal(L, "panto"); + lua_bridge.pushPantoTable(L); _ = c.lua_getfield(L, -1, "ext"); _ = c.lua_getfield(L, -1, "register_tool"); // Stack: ..., panto, ext, register_tool. Collapse to just @@ -974,7 +974,7 @@ fn invokeCoroutineSync( /// stores into the matching slot. fn installRecordResult(self: *LuaRuntime) !void { const L = self.L; - _ = c.lua_getglobal(L, "panto"); + lua_bridge.pushPantoTable(L); if (c.lua_type(L, -1) != lua_bridge.T_TABLE) { c.lua_settop(L, c.lua_gettop(L) - 1); return RuntimeError.LuaInitFailed; @@ -1038,7 +1038,10 @@ fn recordResultC(L: ?*c.lua_State) callconv(.c) c_int { /// Stored in the Lua registry under `self.wrapper_ref`. fn installWrapperClosure(self: *LuaRuntime) !void { const L = self.L; + // `panto` is not a global, so the wrapper closes over the table + // (passed as an argument) rather than looking it up globally. const snippet = + \\local panto = ... \\return function(idx, handler, input) \\ local ok, val = pcall(handler, input) \\ panto._record_result(idx, ok, val) @@ -1049,7 +1052,9 @@ fn installWrapperClosure(self: *LuaRuntime) !void { c.lua_settop(L, c.lua_gettop(L) - 1); return RuntimeError.LuaInitFailed; } - if (c.lua_pcallk(L, 0, 1, 0, 0, null) != 0) { + // Pass the `panto` table as the chunk's vararg argument. + lua_bridge.pushPantoTable(L); + if (c.lua_pcallk(L, 1, 1, 0, 0, null) != 0) { logTopAsError(L, "panto-lua: wrapper closure failed to evaluate"); c.lua_settop(L, c.lua_gettop(L) - 1); return RuntimeError.LuaInitFailed; @@ -1153,7 +1158,12 @@ fn freeResults(results: []panto.ToolCallResult) void { } fn writeTempScript(dir: Io.Dir, name: []const u8, source: []const u8) ![]const u8 { - try dir.writeFile(testing.io, .{ .sub_path = name, .data = source }); + // `panto` is not a global; extensions reach it via `require('panto')`. + // Prepend the require so these tests exercise the real preload path + // without each script repeating the boilerplate. + var src_buf: [16384]u8 = undefined; + const data = try std.fmt.bufPrint(&src_buf, "local panto = require(\"panto\")\n{s}", .{source}); + try dir.writeFile(testing.io, .{ .sub_path = name, .data = data }); var buf: [std.fs.max_path_bytes]u8 = undefined; const n = try dir.realPathFile(testing.io, name, &buf); return testing.allocator.dupe(u8, buf[0..n]); @@ -1428,6 +1438,7 @@ test "directory-style extension can require sibling modules" { try tmp.dir.writeFile(testing.io, .{ .sub_path = "ext/init.lua", .data = + \\local panto = require("panto") \\local util = require("util") \\panto.ext.register_tool { \\ name = "shout", description = "uppercase + bang", |
