feat: PluginPage iframe bridge + CallPluginFunction binding

- PluginPage.svelte: bidirectional postMessage bridge with iframe
  - Handles: ready, get-events, create-event, update-event, delete-event
  - Queues messages until iframe is ready
  - Exports handleDrop() for drag-and-drop from parent
- CallPluginFunction binding: calls arbitrary Lua functions on active plugins
  - Supports dotted paths: 'calendar.create_event' → _G.calendar.create_event
  - JSON params → Lua table conversion
- LuaVM: added DoString(), LState(), VM() public methods
- Plugin: added VM() getter for external access
This commit is contained in:
2026-06-07 16:37:32 +08:00
parent 308772dee8
commit a1d7c7b88b
3 changed files with 266 additions and 12 deletions
+26
View File
@@ -168,6 +168,32 @@ func (vm *LuaVM) SetServices(svc *CoreServices) {
vm.Services = svc
}
// DoString executes an arbitrary Lua script string and returns the first return value.
func (vm *LuaVM) DoString(src string) (string, error) {
vm.mu.Lock()
defer vm.mu.Unlock()
if vm.L == nil || vm.L.IsClosed() {
return "", fmt.Errorf("Lua VM is closed")
}
if err := vm.L.DoString(src); err != nil {
return "", err
}
// Get return value from stack
ret := vm.L.Get(-1)
vm.L.Pop(1)
return ret.String(), nil
}
// LState returns the underlying lua.LState (for table creation).
func (vm *LuaVM) LState() *lua.LState {
return vm.L
}
// VM returns the LuaVM for external use (bindings).
func (p *Plugin) VM() *LuaVM {
return p.vm
}
// callWithTimeout runs a PCall with a timeout and returns the first LValue.
// nargs is the number of function arguments already on the stack.
// Must be called with vm.mu held.