summaryrefslogtreecommitdiff
path: root/src/lua_event_bridge.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua_event_bridge.zig')
-rw-r--r--src/lua_event_bridge.zig82
1 files changed, 41 insertions, 41 deletions
diff --git a/src/lua_event_bridge.zig b/src/lua_event_bridge.zig
index c4acb1d..24bc6fc 100644
--- a/src/lua_event_bridge.zig
+++ b/src/lua_event_bridge.zig
@@ -3,7 +3,7 @@
//! This module bridges the native event machinery in `tui_event.zig` to
//! Lua: it lets a Lua `panto.ext.on(name, handler)` callback participate in
//! the SAME `EventBus` the native side fires, receive a bridged `event`
-//! object (`getComponent`/`setComponent` + payload fields), and either
+//! object (`get_component`/`set_component` + payload fields), and either
//! pass through a native default component, wrap it, or install a
//! brand-new component DEFINED IN LUA.
//!
@@ -401,7 +401,7 @@ pub const EventBridge = struct {
/// The native `Handler.callback` for a bridged Lua handler. Builds the
/// `event` userdata, calls the Lua function with it (synchronously, under
/// a traceback errfunc), and lets the Lua side read/replace the component
-/// via `event:getComponent()` / `event:setComponent()`. Errors in the Lua
+/// via `event:get_component()` / `event:set_component()`. Errors in the Lua
/// handler are logged and swallowed — a broken handler must not abort the
/// event dispatch or the render loop.
fn nativeHandlerCallback(ctx: *anyopaque, event: *Event) void {
@@ -444,7 +444,7 @@ fn nativeHandlerCallback(ctx: *anyopaque, event: *Event) void {
/// Push an `event` userdata onto the stack, carrying a pointer to the
/// bridge (which reaches the active `*Event`). Its metatable exposes
-/// `getComponent`, `setComponent`, and read-only payload fields via
+/// `get_component`, `set_component`, and read-only payload fields via
/// `__index`.
fn pushEventObject(bridge: *EventBridge) !void {
const L = bridge.L;
@@ -456,7 +456,7 @@ fn pushEventObject(bridge: *EventBridge) !void {
/// Lazily create the `event` userdata metatable (by name, so
/// `luaL_checkudata` recognizes it) and leave it on the stack. Its
-/// `__index` is a function resolving `getComponent`/`setComponent` and
+/// `__index` is a function resolving `get_component`/`set_component` and
/// payload fields.
fn ensureEventMetatable(L: *c.lua_State) void {
// luaL_newmetatable pushes the metatable; returns 1 if freshly created.
@@ -476,11 +476,11 @@ fn eventIndexThunk(L_opt: ?*c.lua_State) callconv(.c) c_int {
if (kptr == null) return 0;
const key = kptr[0..klen];
- if (std.mem.eql(u8, key, "getComponent")) {
+ if (std.mem.eql(u8, key, "get_component")) {
c.lua_pushcclosure(L, eventGetComponentThunk, 0);
return 1;
}
- if (std.mem.eql(u8, key, "setComponent")) {
+ if (std.mem.eql(u8, key, "set_component")) {
c.lua_pushcclosure(L, eventSetComponentThunk, 0);
return 1;
}
@@ -579,13 +579,13 @@ fn pushPayloadField(L: *c.lua_State, ev: *Event, key: []const u8) void {
c.lua_pushnil(L);
}
-/// `event:getComponent()` -> the current component as a native-passthrough
+/// `event:get_component()` -> the current component as a native-passthrough
/// userdata (or nil). The userdata wraps the `Component` (vtable+ptr) so
-/// Lua can pass it straight back to `setComponent` unchanged (§7.5 wrap
+/// Lua can pass it straight back to `set_component` unchanged (§7.5 wrap
/// pattern: the inner is opaque to Lua but re-settable / wrappable).
fn eventGetComponentThunk(L_opt: ?*c.lua_State) callconv(.c) c_int {
const L = L_opt.?;
- // arg 1 is the event userdata (method call `event:getComponent()`).
+ // arg 1 is the event userdata (method call `event:get_component()`).
const ud: **EventBridge = @ptrCast(@alignCast(c.luaL_checkudata(L, 1, eventMtName) orelse return 0));
const bridge = ud.*;
const ev = bridge.active_event orelse {
@@ -600,8 +600,8 @@ fn eventGetComponentThunk(L_opt: ?*c.lua_State) callconv(.c) c_int {
return 1;
}
-/// `event:setComponent(c)` where `c` is EITHER a native-passthrough
-/// userdata (from `getComponent`) OR a Lua component table. A table is
+/// `event:set_component(c)` where `c` is EITHER a native-passthrough
+/// userdata (from `get_component`) OR a Lua component table. A table is
/// bridged into a native `Component` (§7.6); a userdata passes the native
/// component straight through.
fn eventSetComponentThunk(L_opt: ?*c.lua_State) callconv(.c) c_int {
@@ -618,20 +618,20 @@ fn eventSetComponentThunk(L_opt: ?*c.lua_State) callconv(.c) c_int {
ev.setComponent(cud.*);
return 0;
}
- return c.luaL_error(L, "setComponent: unknown userdata (expected a component)");
+ return c.luaL_error(L, "set_component: unknown userdata (expected a component)");
}
if (ty == lua_bridge.T_TABLE) {
const comp = bridge.makeBridgedComponent(2) catch {
- return c.luaL_error(L, "setComponent: failed to bridge Lua component");
+ return c.luaL_error(L, "set_component: failed to bridge Lua component");
};
ev.setComponent(comp);
return 0;
}
- return c.luaL_error(L, "setComponent: argument must be a component (table or native handle)");
+ return c.luaL_error(L, "set_component: argument must be a component (table or native handle)");
}
/// Push a native `Component` as a passthrough userdata with the
-/// native-component metatable (so `setComponent` can recover it).
+/// native-component metatable (so `set_component` can recover it).
fn pushNativeComponent(L: *c.lua_State, comp: Component) void {
const ud: *Component = @ptrCast(@alignCast(c.lua_newuserdatauv(L, @sizeOf(Component), 0).?));
ud.* = comp;
@@ -781,7 +781,7 @@ test "Lua-defined component renders lines through the bridged vtable" {
// A handler that sets a Lua component whose render returns two lines.
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({
+ \\ e:set_component({
\\ render = function(self, width) return { "hello", "world" } end,
\\ })
\\end)
@@ -820,7 +820,7 @@ test "bridged component render truncates to the width contract" {
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({
+ \\ e:set_component({
\\ render = function(self, width) return { "abcdefghij" } end,
\\ })
\\end)
@@ -849,7 +849,7 @@ test "bridged component render error yields a safe fallback line, not a crash" {
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({
+ \\ e:set_component({
\\ render = function(self, width) error("boom") end,
\\ })
\\end)
@@ -903,12 +903,12 @@ test "wrap pattern: Lua reads the native default, wraps it, and renders through
var nd = NativeDefault{ .cache = RenderCache.init(testing.allocator) };
defer nd.cache.deinit();
- // Handler: read the native default via getComponent, store it, set a Lua
+ // Handler: read the native default via get_component, store it, set a Lua
// component that renders "[" .. inner_first_line .. "]".
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ local inner = e:getComponent() -- native passthrough handle
- \\ e:setComponent({
+ \\ local inner = e:get_component() -- native passthrough handle
+ \\ e:set_component({
\\ inner = inner,
\\ render = function(self, width)
\\ -- We cannot call the native inner's render from Lua (it has no
@@ -933,7 +933,7 @@ test "wrap pattern: Lua reads the native default, wraps it, and renders through
test "skills-style claim-by-name (§7.5) works end-to-end through the Lua bridge" {
// The canonical extension pattern: a Lua handler subscribes to `tool`,
// returns early UNLESS event.tool_name matches its tool, and otherwise
- // setComponent's a Lua-defined component. We fire two tool events through
+ // set_component's a Lua-defined component. We fire two tool events through
// the NATIVE bus and assert only the matching name is claimed (its Lua
// component renders), while a non-matching name keeps the native default.
const L = c.luaL_newstate() orelse return error.LuaInitFailed;
@@ -955,7 +955,7 @@ test "skills-style claim-by-name (§7.5) works end-to-end through the Lua bridge
\\panto.ext.on("tool", function(e)
\\ if e.tool_name ~= "skill" then return end -- claim-by-name
\\ local name = e.tool_name -- snapshot at handler time
- \\ e:setComponent({
+ \\ e:set_component({
\\ render = function(self, width) return { "SKILL:" .. name } end,
\\ })
\\end)
@@ -1011,7 +1011,7 @@ test "skills-style claim-by-name (§7.5) works end-to-end through the Lua bridge
}
}
-test "native-passthrough get/set round-trip: setComponent(getComponent()) keeps the native default" {
+test "native-passthrough get/set round-trip: set_component(get_component()) keeps the native default" {
const L = c.luaL_newstate() orelse return error.LuaInitFailed;
defer c.lua_close(L);
c.luaL_openlibs(L);
@@ -1049,7 +1049,7 @@ test "native-passthrough get/set round-trip: setComponent(getComponent()) keeps
// Handler passes the native default straight back through.
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent(e:getComponent())
+ \\ e:set_component(e:get_component())
\\end)
);
try harvestOnInto(&bridge);
@@ -1112,7 +1112,7 @@ test "bridged render: a long error on a NARROW width still satisfies the width c
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({
+ \\ e:set_component({
\\ render = function(self, width) error("a very long error message that definitely exceeds a narrow terminal width") end,
\\ })
\\end)
@@ -1153,7 +1153,7 @@ test "bridged render: non-array / nil / non-string returns each yield a safe fal
\\idx = 0
\\panto.ext.on("tool", function(e)
\\ idx = idx + 1
- \\ e:setComponent({ render = components[idx] })
+ \\ e:set_component({ render = components[idx] })
\\end)
);
try harvestOnInto(&bridge);
@@ -1183,7 +1183,7 @@ test "bridged render: empty array renders zero lines (no fallback)" {
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, width) return {} end })
+ \\ e:set_component({ render = function(self, width) return {} end })
\\end)
);
try harvestOnInto(&bridge);
@@ -1213,7 +1213,7 @@ test "bridged render: UTF-8 line truncates on codepoint boundaries to the width"
// exactly 3 codepoints (6 bytes), not split a 2-byte sequence.
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, width) return { "\195\169\195\169\195\169\195\169\195\169" } end })
+ \\ e:set_component({ render = function(self, width) return { "\195\169\195\169\195\169\195\169\195\169" } end })
\\end)
);
try harvestOnInto(&bridge);
@@ -1247,7 +1247,7 @@ test "bridged firstLineChanged is cache-derived: append stays near the tail" {
try runScript(L,
\\n = 2
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({
+ \\ e:set_component({
\\ render = function(self, width)
\\ local t = {}
\\ for i = 1, n do t[i] = "line" .. i end
@@ -1296,7 +1296,7 @@ test "bridged firstLineChanged: a mid-line replace reports the changed line, shr
try runScript(L,
\\lines = { "a", "b", "c" }
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, width) return lines end })
+ \\ e:set_component({ render = function(self, width) return lines end })
\\end)
);
try harvestOnInto(&bridge);
@@ -1343,7 +1343,7 @@ test "bridged handleInput round-trips: a Lua method mutates state the next rende
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({
+ \\ e:set_component({
\\ buf = "",
\\ handleInput = function(self, data) self.buf = self.buf .. data end,
\\ render = function(self, width) return { self.buf } end,
@@ -1390,7 +1390,7 @@ test "bridged component: invalidate frees the ref+cache eagerly; teardown is lea
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, width) return { "x", "y" } end })
+ \\ e:set_component({ render = function(self, width) return { "x", "y" } end })
\\end)
);
try harvestOnInto(&bridge);
@@ -1537,12 +1537,12 @@ test "claim-by-name at tool_details swaps over the start default; releasing the
try runScript(L,
\\-- At block_start the name is unknown; set a placeholder Lua component.
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, w) return { "tool (?)" } end })
+ \\ e:set_component({ render = function(self, w) return { "tool (?)" } end })
\\end)
\\-- At tool_details, claim by name and swap in the real component.
\\panto.ext.on("tool_details", function(e)
\\ if e.tool_name ~= "skill" then return end
- \\ e:setComponent({ render = function(self, w) return { "SKILL" } end })
+ \\ e:set_component({ render = function(self, w) return { "SKILL" } end })
\\end)
);
try harvestOnInto(&bridge);
@@ -1560,7 +1560,7 @@ test "claim-by-name at tool_details swaps over the start default; releasing the
try testing.expectEqual(@as(usize, 1), bridge.components.items.len);
// tool_details: seed the event with the CURRENT override (the placeholder),
- // mirroring how the App seeds getComponent with the current component. The
+ // mirroring how the App seeds get_component with the current component. The
// handler claims "skill" and swaps in "SKILL".
const details = bus.fire("tool_details", start, .{ .tool = .{ .index = 0, .tool_name = "skill", .id = "c0" } }).?;
try testing.expect(details.ptr != start.ptr); // a NEW component
@@ -1614,7 +1614,7 @@ test "claim-by-name at tool_details swaps over the start default; releasing the
test "intra-emit clobber: two handlers each mint a Lua component in ONE emit; both are tracked and freed at teardown (no true leak)" {
// §7.3 "last-wins-blind": when two handlers for the SAME event each call
- // setComponent within a single emit, the bus keeps only the last as
+ // set_component within a single emit, the bus keeps only the last as
// `current`. The App records only that last one as the entry's override,
// so the FIRST handler's freshly-minted Lua component is never handed to
// `releaseOverride` (the App never sees it). It is therefore NOT released
@@ -1626,8 +1626,8 @@ test "intra-emit clobber: two handlers each mint a Lua component in ONE emit; bo
// - but it IS per-emit accumulation: a clobbering handler chain grows
// `bridge.components` by one orphan per clobber for the runtime's life.
//
- // The documented mitigation is the §7.3 wrap pattern (getComponent ->
- // wrap -> setComponent), under which no component is orphaned because each
+ // The documented mitigation is the §7.3 wrap pattern (get_component ->
+ // wrap -> set_component), under which no component is orphaned because each
// handler decorates the current one instead of minting a rival. A handler
// that clobbers blind is at fault per the plan; the resource is still
// reclaimed at teardown, so correctness (no UAF / no true leak) holds.
@@ -1646,10 +1646,10 @@ test "intra-emit clobber: two handlers each mint a Lua component in ONE emit; bo
// component, ignoring the current one.
try runScript(L,
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, w) return { "FIRST" } end })
+ \\ e:set_component({ render = function(self, w) return { "FIRST" } end })
\\end)
\\panto.ext.on("tool", function(e)
- \\ e:setComponent({ render = function(self, w) return { "SECOND" } end })
+ \\ e:set_component({ render = function(self, w) return { "SECOND" } end })
\\end)
);
try harvestOnInto(&bridge);