Implement self-hosted debug console and @external decorator
This commit completes the self-hosting of Ritz's debug console and
introduces the @external decorator for elegant JavaScript bridge functions.
## Major Features
### 1. Self-Hosted Debug Console (DebugConsole.py)
- Entire debug console UI written in Ritz itself
- Signal-based state management for toggle functionality
- Displays runtime stats (memory, signals, DOM nodes, logs)
- Live reactive updates when signals change in main app
- Keyboard shortcut support (Ctrl+`)
### 2. @external Decorator for JavaScript Bridges
- Pythonic decorator syntax: @external or @bridge
- Parser automatically recognizes and tracks external functions
- Codegen emits proper LLVM declarations
- No more hacky string checks (startswith("js_"))
- Clean, declarative bridge function definitions
Example:
```python
@external
def js_toggle_debug_console():
pass
def toggle():
js_toggle_debug_console() # Clean call to JS bridge
```
### 3. Enhanced RitzLoader Debug Mode
- `new RitzLoader({ debug: true })` auto-loads DebugConsole.wasm
- Keyboard shortcut registration (Ctrl+` toggle)
- Runtime stats injection (memory, signals, DOM nodes)
- Automatic status element hiding when debug enabled
- Debug console isolated in separate WASM runtime
## Bug Fixes
- Fixed reactive text node scoping (prevent global name collisions)
- Fixed CSS specificity for debug console status (use #ritz-debug)
- Fixed signal cross-contamination between runtimes (scope to rootElement)
- Fixed parser to handle expression statements in function bodies
- Fixed conditional branch rendering (append children to wrapper divs)
## Infrastructure Improvements
- Added H4 and Pre elements to syntax.py
- Parser handles @external decorator on top-level functions
- Codegen pre-collects external functions before emitting declarations
- Runtime scopes querySelector to prevent cross-runtime interference
- Debug stats update reactively on every signal change
## Files Added/Modified
New files:
- examples/runtime/DebugConsole.py - Self-hosted debug UI
- examples/runtime/DebugConsole.wasm - Compiled debug console (1.8KB)
- PHASE4_CLEANUP.md - Next phase planning document
Modified:
- ritz/parser.py - @external decorator support
- ritz/llvm_codegen_signals.py - External function handling
- ritz/syntax.py - Added external/bridge decorators, H4, Pre
- examples/runtime/ritz-runtime.js - Debug mode, stats updates
- examples/runtime/styles.css - Merged debug styles
- examples/template.html - Debug mode enabled by default
- examples/highfive/HighFive.html - Simplified using template
## Known Issues (Addressed in PHASE4_CLEANUP.md)
1. Debug console shifts page RIGHT (should shift LEFT)
2. Toggle implementation un-Ritzy (calls JS to manipulate DOM)
- Should use reactive class binding + @event decorator
- Needs event object bridge for keyboard events
3. Missing test infrastructure
## Next Steps (Phase 4)
See PHASE4_CLEANUP.md for detailed plan:
- Implement reactive class binding (signal-driven classes)
- Add @event decorator for declarative event registration
- Build event object bridge (access event.key, event.ctrlKey)
- Create Python test mode (execute without browser)
- Add comprehensive test suite
- Update all examples to use new patterns
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
ddd2c03a9d
commit
ea7dadc5ae
20 files changed
+1324
-70
No files matched your search
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
Ritz Debug Console - Self-hosted debug interface written in Ritz itself!
|
||||
|
||||
This demonstrates Ritz's capability to build complex interactive UIs with:
|
||||
- Signal-based state management
|
||||
- Event handling
|
||||
- Conditional rendering
|
||||
- Dynamic content updates
|
||||
|
||||
The entire debug console - state, UI, and interactions - is written in Ritz!
|
||||
"""
|
||||
|
||||
from ritz.syntax import *
|
||||
|
||||
|
||||
@external
|
||||
def js_toggle_debug_console():
|
||||
"""External JavaScript function to toggle debug console visibility."""
|
||||
pass # Implementation provided by JavaScript runtime
|
||||
|
||||
|
||||
@component
|
||||
def DebugConsole():
|
||||
"""
|
||||
Self-hosted debug console for Ritz applications.
|
||||
|
||||
Shows runtime information, memory stats, and console commands.
|
||||
"""
|
||||
def toggle():
|
||||
"""Toggle debug console visibility by calling JavaScript bridge."""
|
||||
js_toggle_debug_console()
|
||||
|
||||
# Start hidden - JavaScript will handle toggling via class manipulation
|
||||
with Div(class_='ritz-debug hidden', id='ritz-debug'):
|
||||
# Header with toggle button
|
||||
with Div(class_='debug-header'):
|
||||
with H3():
|
||||
yield '🎭 Ritz Debug'
|
||||
with Button(onclick=toggle):
|
||||
yield '×'
|
||||
|
||||
# Status indicator
|
||||
with Div(class_='status success', id='status'):
|
||||
yield '✅ Main loaded!'
|
||||
|
||||
# Debug content sections
|
||||
with Div(class_='debug-content'):
|
||||
# Component info
|
||||
with Div(class_='debug-section'):
|
||||
with H4():
|
||||
yield 'COMPONENT'
|
||||
with Pre():
|
||||
yield 'Main.wasm (Multi-Part Switches)'
|
||||
|
||||
# Features section
|
||||
with Div(class_='debug-section'):
|
||||
with H4():
|
||||
yield 'FEATURES'
|
||||
with Pre():
|
||||
yield '✓ Python source to WASM\n'
|
||||
yield '✓ Reactive signals (no vDOM)\n'
|
||||
yield '✓ Conditional CSR (match/case)\n'
|
||||
yield '✓ Event handlers\n'
|
||||
yield '✓ Self-hosted debug console!\n'
|
||||
|
||||
# Runtime stats section
|
||||
with Div(class_='debug-section'):
|
||||
with H4():
|
||||
yield 'RUNTIME STATS'
|
||||
with Pre():
|
||||
yield 'Memory: JavaScript will update\n'
|
||||
yield 'Signals: JavaScript will update\n'
|
||||
yield 'DOM nodes: JavaScript will update\n'
|
||||
|
||||
# Console commands section
|
||||
with Div(class_='debug-section'):
|
||||
with H4():
|
||||
yield 'CONSOLE COMMANDS'
|
||||
with Pre():
|
||||
yield 'ritzRuntime.getLog()\n'
|
||||
yield 'ritzRuntime.nodes.size\n'
|
||||
yield 'ritzInstance.exports\n'
|
||||
|
||||
# Toggle hint (appears on page load)
|
||||
with Div(class_='debug-toggle-hint'):
|
||||
yield 'Press Ctrl+` to toggle debug'
|
||||
|
||||
|
||||
@component
|
||||
def RitzMain():
|
||||
"""Entry point for debug console component."""
|
||||
yield DebugConsole()
|
||||
Reference in new issue
Block a user