Implement RitzMain() convention and Main.wasm standard
**Convention: RitzMain() entry point**
Every Ritz file now requires a `@component def RitzMain()` as the entry point.
This provides a consistent, predictable entry point for all applications.
**Universal Main.wasm output**
Build system now always outputs Main.wasm instead of ComponentName.wasm.
This means every example uses the exact same HTML boilerplate!
**Changes:**
**Codegen (llvm_codegen_signals.py):**
- Check for RitzMain component at generation time
- Error if RitzMain not found: "No RitzMain component found!"
- Always call `render_RitzMain()` from main() entry point
- Fix: Scope reactive text nodes to components (`@reactive_text_ComponentName_N_node`)
- Prevents global name collisions when multiple components have reactive text
**Build (build.py):**
- Output Main.wasm in same directory as source file
- Output Main.ll (LLVM IR) for inspection
- Convention over configuration!
**Loader (ritz-runtime.js):**
- Auto-detect component name from WASM filename
- `new RitzLoader().load('Main.wasm')` - no second parameter needed!
- Component name used only for status messages
**Template (examples/template.html):**
- Minimal boilerplate - literally 25 lines
- Just copy and change nothing!
- Loads Main.wasm - works for every example
**Styles (examples/runtime/styles.css):**
- Shared styles for all examples
- Clean, modern defaults
- App container, buttons, inputs, typography
**Example (HighFive):**
```python
@component
def HighFive():
# ... component logic
@component
def RitzMain():
"""Entry point - required!"""
yield HighFive()
```
**Result:**
✅ Every example: copy template.html, change nothing
✅ Every example: builds to Main.wasm
✅ Consistent entry point: RitzMain()
✅ No more component name boilerplate
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
999327172e
commit
ddd2c03a9d
9 files changed
+261
-52
No files matched your search
@@ -86,10 +86,10 @@ ritzInstance.exports.increment()</pre>
|
|||||||
// Wait for DOM to be ready
|
// Wait for DOM to be ready
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
new RitzLoader().load('HighFive.wasm', 'HighFive');
|
new RitzLoader().load('Main.wasm');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
new RitzLoader().load('HighFive.wasm', 'HighFive');
|
new RitzLoader().load('Main.wasm');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -24,3 +24,9 @@ def HighFive():
|
|||||||
|
|
||||||
with Button(onclick=increment):
|
with Button(onclick=increment):
|
||||||
yield "High Five!"
|
yield "High Five!"
|
||||||
|
|
||||||
|
|
||||||
|
@component
|
||||||
|
def RitzMain():
|
||||||
|
"""Entry point - required for all Ritz applications."""
|
||||||
|
yield HighFive()
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
; Generated by Ritz Framework with Signals
|
||||||
|
; Components: HighFive, RitzMain
|
||||||
|
|
||||||
|
; String constants
|
||||||
|
@.str.0 = private unnamed_addr constant [13 x i8] c"High fives: \00"
|
||||||
|
@.str.1 = private unnamed_addr constant [4 x i8] c"div\00"
|
||||||
|
@.str.2 = private unnamed_addr constant [6 x i8] c"class\00"
|
||||||
|
@.str.3 = private unnamed_addr constant [14 x i8] c"high-five-app\00"
|
||||||
|
@.str.4 = private unnamed_addr constant [2 x i8] c"p\00"
|
||||||
|
@.str.5 = private unnamed_addr constant [25 x i8] c"Give me a high five! ✋\00"
|
||||||
|
@.str.6 = private unnamed_addr constant [6 x i8] c"count\00"
|
||||||
|
@.str.7 = private unnamed_addr constant [7 x i8] c"button\00"
|
||||||
|
@.str.8 = private unnamed_addr constant [6 x i8] c"click\00"
|
||||||
|
@.str.9 = private unnamed_addr constant [10 x i8] c"increment\00"
|
||||||
|
@.str.10 = private unnamed_addr constant [11 x i8] c"High Five!\00"
|
||||||
|
|
||||||
|
; JavaScript bridge function declarations
|
||||||
|
declare i32 @js_create_element(i8*)
|
||||||
|
declare i32 @js_create_text(i8*)
|
||||||
|
declare i32 @js_create_text_with_int(i8*, i32)
|
||||||
|
declare void @js_append_child(i32, i32)
|
||||||
|
declare void @js_set_attribute(i32, i8*, i8*)
|
||||||
|
declare void @js_set_root(i32)
|
||||||
|
declare void @js_bind_event(i32, i8*, i8*)
|
||||||
|
declare void @js_update_text_content(i32, i8*)
|
||||||
|
declare void @js_update_text_with_int(i32, i8*, i32)
|
||||||
|
declare i32 @js_create_marker()
|
||||||
|
declare void @js_replace_at_marker(i32, i32, i32)
|
||||||
|
|
||||||
|
; Signal storage for HighFive (reactive state in WASM memory)
|
||||||
|
@signal_HighFive_high_fives = global i32 0
|
||||||
|
|
||||||
|
; Reactive text node storage for HighFive
|
||||||
|
@reactive_text_HighFive_0_node = global i32 0
|
||||||
|
|
||||||
|
; Signal helper functions
|
||||||
|
define i32 @get_high_fives() {
|
||||||
|
entry:
|
||||||
|
%val = load i32, i32* @signal_HighFive_high_fives
|
||||||
|
ret i32 %val
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @set_high_fives(i32 %newval) {
|
||||||
|
entry:
|
||||||
|
store i32 %newval, i32* @signal_HighFive_high_fives
|
||||||
|
; TODO: Trigger DOM update callback
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Event handler: increment
|
||||||
|
define void @increment() {
|
||||||
|
entry:
|
||||||
|
%var0 = load i32, i32* @signal_HighFive_high_fives
|
||||||
|
%var1 = add i32 %var0, 1
|
||||||
|
store i32 %var1, i32* @signal_HighFive_high_fives
|
||||||
|
%var2 = load i32, i32* @reactive_text_HighFive_0_node
|
||||||
|
%var3 = getelementptr inbounds [13 x i8], [13 x i8]* @.str.0, i32 0, i32 0
|
||||||
|
%var4 = load i32, i32* @signal_HighFive_high_fives
|
||||||
|
call void @js_update_text_with_int(i32 %var2, i8* %var3, i32 %var4)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Component render function
|
||||||
|
define i32 @render_HighFive() {
|
||||||
|
entry:
|
||||||
|
%var6 = getelementptr inbounds [4 x i8], [4 x i8]* @.str.1, i32 0, i32 0
|
||||||
|
%var5 = call i32 @js_create_element(i8* %var6)
|
||||||
|
%var7 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||||||
|
%var8 = getelementptr inbounds [14 x i8], [14 x i8]* @.str.3, i32 0, i32 0
|
||||||
|
call void @js_set_attribute(i32 %var5, i8* %var7, i8* %var8)
|
||||||
|
%var10 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.4, i32 0, i32 0
|
||||||
|
%var9 = call i32 @js_create_element(i8* %var10)
|
||||||
|
%var11 = call i32 @js_create_text(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @.str.5, i32 0, i32 0))
|
||||||
|
call void @js_append_child(i32 %var9, i32 %var11)
|
||||||
|
call void @js_append_child(i32 %var5, i32 %var9)
|
||||||
|
%var13 = getelementptr inbounds [2 x i8], [2 x i8]* @.str.4, i32 0, i32 0
|
||||||
|
%var12 = call i32 @js_create_element(i8* %var13)
|
||||||
|
%var14 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.2, i32 0, i32 0
|
||||||
|
%var15 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.6, i32 0, i32 0
|
||||||
|
call void @js_set_attribute(i32 %var12, i8* %var14, i8* %var15)
|
||||||
|
%var16 = getelementptr inbounds [13 x i8], [13 x i8]* @.str.0, i32 0, i32 0
|
||||||
|
%var17 = load i32, i32* @signal_HighFive_high_fives
|
||||||
|
%var18 = call i32 @js_create_text_with_int(i8* %var16, i32 %var17)
|
||||||
|
store i32 %var18, i32* @reactive_text_HighFive_0_node
|
||||||
|
call void @js_append_child(i32 %var12, i32 %var18)
|
||||||
|
call void @js_append_child(i32 %var5, i32 %var12)
|
||||||
|
%var20 = getelementptr inbounds [7 x i8], [7 x i8]* @.str.7, i32 0, i32 0
|
||||||
|
%var19 = call i32 @js_create_element(i8* %var20)
|
||||||
|
%var21 = getelementptr inbounds [6 x i8], [6 x i8]* @.str.8, i32 0, i32 0
|
||||||
|
%var22 = getelementptr inbounds [10 x i8], [10 x i8]* @.str.9, i32 0, i32 0
|
||||||
|
call void @js_bind_event(i32 %var19, i8* %var21, i8* %var22)
|
||||||
|
%var23 = call i32 @js_create_text(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.10, i32 0, i32 0))
|
||||||
|
call void @js_append_child(i32 %var19, i32 %var23)
|
||||||
|
call void @js_append_child(i32 %var5, i32 %var19)
|
||||||
|
ret i32 %var5
|
||||||
|
}
|
||||||
|
|
||||||
|
; Reactive text node storage for RitzMain
|
||||||
|
@reactive_text_RitzMain_0_node = global i32 0
|
||||||
|
|
||||||
|
; Component render function
|
||||||
|
define i32 @render_RitzMain() {
|
||||||
|
entry:
|
||||||
|
%var24 = call i32 @render_HighFive()
|
||||||
|
ret i32 %var24
|
||||||
|
}
|
||||||
|
|
||||||
|
; Main entry point
|
||||||
|
define void @main() {
|
||||||
|
entry:
|
||||||
|
%root = call i32 @render_RitzMain()
|
||||||
|
call void @js_set_root(i32 %root)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
@@ -288,8 +288,14 @@ class RitzLoader {
|
|||||||
this.onError = options.onError || ((err) => console.error(err));
|
this.onError = options.onError || ((err) => console.error(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(wasmPath, componentName, props = {}) {
|
async load(wasmPath, componentName = null, props = {}) {
|
||||||
try {
|
try {
|
||||||
|
// Auto-detect component name from wasm filename if not provided
|
||||||
|
if (!componentName) {
|
||||||
|
// Extract from path: "Main.wasm" → "Main", "path/to/Main.wasm" → "Main"
|
||||||
|
componentName = wasmPath.split('/').pop().replace('.wasm', '');
|
||||||
|
}
|
||||||
|
|
||||||
this.setStatus('⏳ Creating runtime...');
|
this.setStatus('⏳ Creating runtime...');
|
||||||
const runtime = new RitzRuntime(this.rootElement);
|
const runtime = new RitzRuntime(this.rootElement);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/* Ritz Framework - Shared Example Styles */
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 40px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#status {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 12px 20px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status.success {
|
||||||
|
background: #d4edda;
|
||||||
|
border-color: #c3e6cb;
|
||||||
|
color: #155724;
|
||||||
|
}
|
||||||
|
|
||||||
|
#status.error {
|
||||||
|
background: #f8d7da;
|
||||||
|
border-color: #f5c6cb;
|
||||||
|
color: #721c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
background: #0066cc;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #0052a3;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, textarea {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus, select:focus, textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #0066cc;
|
||||||
|
box-shadow: 0 0 0 3px rgba(0,102,204,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
+11
-33
@@ -3,45 +3,23 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{TITLE}} - Ritz Framework</title>
|
<title>Ritz Example</title>
|
||||||
<link rel="stylesheet" href="../runtime/ritz-debug.css">
|
<link rel="stylesheet" href="../runtime/styles.css">
|
||||||
<link rel="stylesheet" href="{{COMPONENT}}.css">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<div id="ritz-debug" class="ritz-debug hidden">
|
<div id="status"></div>
|
||||||
<div class="debug-header">
|
|
||||||
<h3>🎭 Ritz Debug</h3>
|
|
||||||
<button onclick="ritzDebug.toggle()">×</button>
|
|
||||||
</div>
|
|
||||||
<div id="status" class="status">Loading...</div>
|
|
||||||
<div class="debug-content">
|
|
||||||
<div class="debug-section">
|
|
||||||
<h4>Pipeline</h4>
|
|
||||||
<pre>{{COMPONENT}}.py → AST → IR → LLVM → WASM</pre>
|
|
||||||
</div>
|
|
||||||
<div class="debug-section">
|
|
||||||
<h4>Commands</h4>
|
|
||||||
<pre>ritzRuntime.getLog()
|
|
||||||
ritzInstance.exports</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="../runtime/ritz-runtime.js"></script>
|
<script src="../runtime/ritz-runtime.js"></script>
|
||||||
<script src="../runtime/ritz-debug.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
// Load component
|
// Load Main.wasm - automatically calls RitzMain() component
|
||||||
const loader = new RitzLoader({
|
if (document.readyState === 'loading') {
|
||||||
rootElement: document.getElementById('app'),
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
statusElement: document.getElementById('status'),
|
new RitzLoader().load('Main.wasm');
|
||||||
onLoad: (runtime, instance) => {
|
});
|
||||||
console.log('✅ Component loaded');
|
} else {
|
||||||
console.log('Debug: ritzRuntime, ritzInstance');
|
new RitzLoader().load('Main.wasm');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
loader.load('{{COMPONENT}}.wasm', '{{COMPONENT}}');
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+3
-2
@@ -39,7 +39,7 @@ def build_component(component_file: Path, output_file: Path, debug: bool = False
|
|||||||
print(" [3/4] Generating LLVM IR...")
|
print(" [3/4] Generating LLVM IR...")
|
||||||
llvm_ir = generate_llvm_ir(ir)
|
llvm_ir = generate_llvm_ir(ir)
|
||||||
|
|
||||||
# Save LLVM IR for inspection
|
# Save LLVM IR for inspection (always Main.ll)
|
||||||
ll_file = output_file.with_suffix(".ll")
|
ll_file = output_file.with_suffix(".ll")
|
||||||
ll_file.write_text(llvm_ir)
|
ll_file.write_text(llvm_ir)
|
||||||
print(f" Saved LLVM IR: {ll_file}")
|
print(f" Saved LLVM IR: {ll_file}")
|
||||||
@@ -130,7 +130,8 @@ def main() -> None:
|
|||||||
if args.output:
|
if args.output:
|
||||||
output_file = args.output
|
output_file = args.output
|
||||||
else:
|
else:
|
||||||
output_file = args.component.with_suffix(".wasm")
|
# Convention: always output Main.wasm in the same directory as the component
|
||||||
|
output_file = args.component.parent / "Main.wasm"
|
||||||
|
|
||||||
# Ensure output directory exists
|
# Ensure output directory exists
|
||||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|||||||
@@ -109,9 +109,13 @@ class SignalLLVMIRGenerator:
|
|||||||
self._emit_conditional_functions()
|
self._emit_conditional_functions()
|
||||||
self._emit_component(component)
|
self._emit_component(component)
|
||||||
|
|
||||||
# Emit main entry point for the last (top-level) component
|
# Emit main entry point - always looks for RitzMain component
|
||||||
if self.components:
|
ritz_main = next((c for c in self.components if c["name"] == "RitzMain"), None)
|
||||||
self._emit_main_entry(self.components[-1]["name"])
|
if not ritz_main:
|
||||||
|
raise ValueError(
|
||||||
|
"No RitzMain component found! Every Ritz file must have a @component def RitzMain() as entry point."
|
||||||
|
)
|
||||||
|
self._emit_main_entry()
|
||||||
|
|
||||||
# Prepend string constants
|
# Prepend string constants
|
||||||
return self._finalize_with_strings()
|
return self._finalize_with_strings()
|
||||||
@@ -425,15 +429,15 @@ class SignalLLVMIRGenerator:
|
|||||||
self.lines.append("")
|
self.lines.append("")
|
||||||
|
|
||||||
def _emit_reactive_text_globals(self) -> None:
|
def _emit_reactive_text_globals(self) -> None:
|
||||||
"""Emit global storage for reactive text node references."""
|
"""Emit global storage for reactive text node references (scoped to component)."""
|
||||||
if not self.reactive_text_nodes:
|
if not self.reactive_text_nodes:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.lines.append("; Reactive text node storage")
|
self.lines.append(f"; Reactive text node storage for {self.current_component}")
|
||||||
for text_info in self.reactive_text_nodes:
|
for text_info in self.reactive_text_nodes:
|
||||||
text_id = text_info["id"]
|
text_id = text_info["id"]
|
||||||
# Store text node reference so we can update its content later
|
# Store text node reference so we can update its content later (scoped to component)
|
||||||
self.lines.append(f"@reactive_text_{text_id}_node = global i32 0")
|
self.lines.append(f"@reactive_text_{self.current_component}_{text_id}_node = global i32 0")
|
||||||
self.lines.append("")
|
self.lines.append("")
|
||||||
|
|
||||||
def _emit_function_declarations(self) -> None:
|
def _emit_function_declarations(self) -> None:
|
||||||
@@ -629,9 +633,9 @@ class SignalLLVMIRGenerator:
|
|||||||
if not text_info:
|
if not text_info:
|
||||||
return # Text node not found
|
return # Text node not found
|
||||||
|
|
||||||
# Load the text node reference
|
# Load the text node reference (scoped to component)
|
||||||
node_var = self._new_var()
|
node_var = self._new_var()
|
||||||
self.lines.append(f" %{node_var} = load i32, i32* @reactive_text_{text_id}_node")
|
self.lines.append(f" %{node_var} = load i32, i32* @reactive_text_{self.current_component}_{text_id}_node")
|
||||||
|
|
||||||
# Build the f-string text
|
# Build the f-string text
|
||||||
result = self._build_fstring_text(text_info["fstring"])
|
result = self._build_fstring_text(text_info["fstring"])
|
||||||
@@ -933,12 +937,12 @@ class SignalLLVMIRGenerator:
|
|||||||
self.lines.append("}")
|
self.lines.append("}")
|
||||||
self.lines.append("")
|
self.lines.append("")
|
||||||
|
|
||||||
def _emit_main_entry(self, component_name: str) -> None:
|
def _emit_main_entry(self) -> None:
|
||||||
"""Emit main entry point that renders top-level component and sets root."""
|
"""Emit main entry point that renders RitzMain component and sets root."""
|
||||||
self.lines.append("; Main entry point")
|
self.lines.append("; Main entry point")
|
||||||
self.lines.append("define void @main() {")
|
self.lines.append("define void @main() {")
|
||||||
self.lines.append("entry:")
|
self.lines.append("entry:")
|
||||||
self.lines.append(f" %root = call i32 @render_{component_name}()")
|
self.lines.append(" %root = call i32 @render_RitzMain()")
|
||||||
self.lines.append(" call void @js_set_root(i32 %root)")
|
self.lines.append(" call void @js_set_root(i32 %root)")
|
||||||
self.lines.append(" ret void")
|
self.lines.append(" ret void")
|
||||||
self.lines.append("}")
|
self.lines.append("}")
|
||||||
@@ -1376,8 +1380,8 @@ class SignalLLVMIRGenerator:
|
|||||||
empty_ptr = self._emit_string_ptr("")
|
empty_ptr = self._emit_string_ptr("")
|
||||||
self.lines.append(f" %{text_var} = call i32 @js_create_text(i8* {empty_ptr})")
|
self.lines.append(f" %{text_var} = call i32 @js_create_text(i8* {empty_ptr})")
|
||||||
|
|
||||||
# Store the text node reference for reactive updates
|
# Store the text node reference for reactive updates (scoped to component)
|
||||||
self.lines.append(f" store i32 %{text_var}, i32* @reactive_text_{text_id}_node")
|
self.lines.append(f" store i32 %{text_var}, i32* @reactive_text_{self.current_component}_{text_id}_node")
|
||||||
|
|
||||||
return text_var
|
return text_var
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in new issue
Block a user