rip-lang 3.6.1 → 3.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/components.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // CodeGenerator prototype, enabling component compilation. A separate
5
5
  // getComponentRuntime() emits runtime helpers only when components are used.
6
6
  //
7
- // Naming: All render-tree emitters use emit* (ported from v2.5.1's fg* methods).
7
+ // Naming: All render-tree generators use generate* (consistent with compiler).
8
8
 
9
9
  import { TEMPLATE_TAGS } from './tags.js';
10
10
 
@@ -15,7 +15,7 @@ import { TEMPLATE_TAGS } from './tags.js';
15
15
  const BIND_PREFIX = '__bind_';
16
16
  const BIND_SUFFIX = '__';
17
17
 
18
- const LIFECYCLE_HOOKS = new Set(['mounted', 'unmounted', 'updated']);
18
+ const LIFECYCLE_HOOKS = new Set(['beforeMount', 'mounted', 'updated', 'beforeUnmount', 'unmounted']);
19
19
 
20
20
  // ============================================================================
21
21
  // Standalone Utilities
@@ -61,6 +61,16 @@ export function installComponentSupport(CodeGenerator) {
61
61
  // Utilities
62
62
  // ==========================================================================
63
63
 
64
+ /**
65
+ * Localize variable references for block factories.
66
+ * Converts this._elN to _elN and this.x to ctx.x.
67
+ */
68
+ proto.localizeVar = function(line) {
69
+ let result = line.replace(/this\.(_el\d+|_t\d+|_anchor\d+|_frag\d+|_slot\d+|_c\d+|_inst\d+|_empty\d+)/g, '$1');
70
+ result = result.replace(/\bthis\./g, 'ctx.');
71
+ return result;
72
+ };
73
+
64
74
  /**
65
75
  * Check if name is an HTML/SVG tag
66
76
  */
@@ -369,12 +379,12 @@ export function installComponentSupport(CodeGenerator) {
369
379
  * Entry point for processing an entire render block.
370
380
  */
371
381
  proto.buildRender = function(body) {
372
- this._emitElementCount = 0;
373
- this._emitTextCount = 0;
374
- this._emitBlockCount = 0;
375
- this._emitCreateLines = [];
376
- this._emitSetupLines = [];
377
- this._emitBlockFactories = [];
382
+ this._elementCount = 0;
383
+ this._textCount = 0;
384
+ this._blockCount = 0;
385
+ this._createLines = [];
386
+ this._setupLines = [];
387
+ this._blockFactories = [];
378
388
 
379
389
  const statements = Array.isArray(body) && body[0] === 'block' ? body.slice(1) : [body];
380
390
 
@@ -382,68 +392,68 @@ export function installComponentSupport(CodeGenerator) {
382
392
  if (statements.length === 0) {
383
393
  rootVar = 'null';
384
394
  } else if (statements.length === 1) {
385
- rootVar = this.emitNode(statements[0]);
395
+ rootVar = this.generateNode(statements[0]);
386
396
  } else {
387
397
  rootVar = this.newElementVar('frag');
388
- this._emitCreateLines.push(`${rootVar} = document.createDocumentFragment();`);
398
+ this._createLines.push(`${rootVar} = document.createDocumentFragment();`);
389
399
  for (const stmt of statements) {
390
- const childVar = this.emitNode(stmt);
391
- this._emitCreateLines.push(`${rootVar}.appendChild(${childVar});`);
400
+ const childVar = this.generateNode(stmt);
401
+ this._createLines.push(`${rootVar}.appendChild(${childVar});`);
392
402
  }
393
403
  }
394
404
 
395
405
  return {
396
- createLines: this._emitCreateLines,
397
- setupLines: this._emitSetupLines,
398
- blockFactories: this._emitBlockFactories,
406
+ createLines: this._createLines,
407
+ setupLines: this._setupLines,
408
+ blockFactories: this._blockFactories,
399
409
  rootVar
400
410
  };
401
411
  };
402
412
 
403
413
  /** Generate a unique block factory name */
404
414
  proto.newBlockVar = function() {
405
- return `create_block_${this._emitBlockCount++}`;
415
+ return `create_block_${this._blockCount++}`;
406
416
  };
407
417
 
408
418
  /** Generate a unique element variable name */
409
419
  proto.newElementVar = function(hint = 'el') {
410
- return `this._${hint}${this._emitElementCount++}`;
420
+ return `this._${hint}${this._elementCount++}`;
411
421
  };
412
422
 
413
423
  /** Generate a unique text node variable name */
414
424
  proto.newTextVar = function() {
415
- return `this._t${this._emitTextCount++}`;
425
+ return `this._t${this._textCount++}`;
416
426
  };
417
427
 
418
428
  // --------------------------------------------------------------------------
419
- // emitNode — main dispatch for all render tree nodes
429
+ // generateNode — main dispatch for all render tree nodes
420
430
  // --------------------------------------------------------------------------
421
431
 
422
- proto.emitNode = function(sexpr) {
432
+ proto.generateNode = function(sexpr) {
423
433
  // String literal → text node (handle both primitive and String objects)
424
434
  if (typeof sexpr === 'string' || sexpr instanceof String) {
425
435
  const str = sexpr.valueOf();
426
436
  if (str.startsWith('"') || str.startsWith("'") || str.startsWith('`')) {
427
437
  const textVar = this.newTextVar();
428
- this._emitCreateLines.push(`${textVar} = document.createTextNode(${str});`);
438
+ this._createLines.push(`${textVar} = document.createTextNode(${str});`);
429
439
  return textVar;
430
440
  }
431
441
  // Dynamic text binding (reactive member)
432
442
  if (this.reactiveMembers && this.reactiveMembers.has(str)) {
433
443
  const textVar = this.newTextVar();
434
- this._emitCreateLines.push(`${textVar} = document.createTextNode('');`);
435
- this._emitSetupLines.push(`__effect(() => { ${textVar}.data = this.${str}.value; });`);
444
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
445
+ this._setupLines.push(`__effect(() => { ${textVar}.data = this.${str}.value; });`);
436
446
  return textVar;
437
447
  }
438
448
  // Static tag without content
439
449
  const elVar = this.newElementVar();
440
- this._emitCreateLines.push(`${elVar} = document.createElement('${str}');`);
450
+ this._createLines.push(`${elVar} = document.createElement('${str}');`);
441
451
  return elVar;
442
452
  }
443
453
 
444
454
  if (!Array.isArray(sexpr)) {
445
455
  const commentVar = this.newElementVar('c');
446
- this._emitCreateLines.push(`${commentVar} = document.createComment('unknown');`);
456
+ this._createLines.push(`${commentVar} = document.createComment('unknown');`);
447
457
  return commentVar;
448
458
  }
449
459
 
@@ -452,12 +462,12 @@ export function installComponentSupport(CodeGenerator) {
452
462
 
453
463
  // Component instantiation (PascalCase)
454
464
  if (headStr && this.isComponent(headStr)) {
455
- return this.emitChildComponent(headStr, rest);
465
+ return this.generateChildComponent(headStr, rest);
456
466
  }
457
467
 
458
468
  // HTML tag
459
469
  if (headStr && this.isHtmlTag(headStr)) {
460
- return this.emitTag(headStr, [], rest);
470
+ return this.generateTag(headStr, [], rest);
461
471
  }
462
472
 
463
473
  // Property chain (div.class or item.name)
@@ -468,13 +478,13 @@ export function installComponentSupport(CodeGenerator) {
468
478
  if (obj === 'this' && typeof prop === 'string') {
469
479
  if (this.reactiveMembers && this.reactiveMembers.has(prop)) {
470
480
  const textVar = this.newTextVar();
471
- this._emitCreateLines.push(`${textVar} = document.createTextNode('');`);
472
- this._emitSetupLines.push(`__effect(() => { ${textVar}.data = this.${prop}.value; });`);
481
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
482
+ this._setupLines.push(`__effect(() => { ${textVar}.data = this.${prop}.value; });`);
473
483
  return textVar;
474
484
  }
475
485
  if (this.componentMembers && this.componentMembers.has(prop)) {
476
486
  const slotVar = this.newElementVar('slot');
477
- this._emitCreateLines.push(`${slotVar} = this.${prop} instanceof Node ? this.${prop} : (this.${prop} != null ? document.createTextNode(String(this.${prop})) : document.createComment(''));`);
487
+ this._createLines.push(`${slotVar} = this.${prop} instanceof Node ? this.${prop} : (this.${prop} != null ? document.createTextNode(String(this.${prop})) : document.createComment(''));`);
478
488
  return slotVar;
479
489
  }
480
490
  }
@@ -482,13 +492,13 @@ export function installComponentSupport(CodeGenerator) {
482
492
  // HTML tag with classes (div.class)
483
493
  const { tag, classes } = this.collectTemplateClasses(sexpr);
484
494
  if (tag && this.isHtmlTag(tag)) {
485
- return this.emitTag(tag, classes, []);
495
+ return this.generateTag(tag, classes, []);
486
496
  }
487
497
 
488
498
  // General property access (e.g., item.name in a loop)
489
499
  const textVar = this.newTextVar();
490
500
  const exprCode = this.generateInComponent(sexpr, 'value');
491
- this._emitCreateLines.push(`${textVar} = document.createTextNode(String(${exprCode}));`);
501
+ this._createLines.push(`${textVar} = document.createTextNode(String(${exprCode}));`);
492
502
  return textVar;
493
503
  }
494
504
 
@@ -499,56 +509,56 @@ export function installComponentSupport(CodeGenerator) {
499
509
  (head[0][2] === '__cx__' || (head[0][2] instanceof String && head[0][2].valueOf() === '__cx__'))) {
500
510
  const tag = typeof head[0][1] === 'string' ? head[0][1] : head[0][1].valueOf();
501
511
  const classExprs = head.slice(1);
502
- return this.emitDynamicTag(tag, classExprs, rest);
512
+ return this.generateDynamicTag(tag, classExprs, rest);
503
513
  }
504
514
 
505
515
  const { tag, classes } = this.collectTemplateClasses(head);
506
516
  if (tag && this.isHtmlTag(tag)) {
507
517
  // Dynamic class syntax: div.("classes") → (. div __cx__) "classes"
508
518
  if (classes.length === 1 && classes[0] === '__cx__') {
509
- return this.emitDynamicTag(tag, rest, []);
519
+ return this.generateDynamicTag(tag, rest, []);
510
520
  }
511
- return this.emitTag(tag, classes, rest);
521
+ return this.generateTag(tag, classes, rest);
512
522
  }
513
523
  }
514
524
 
515
525
  // Arrow function (children block)
516
526
  if (headStr === '->' || headStr === '=>') {
517
- return this.emitBlock(rest[1]);
527
+ return this.generateTemplateBlock(rest[1]);
518
528
  }
519
529
 
520
530
  // Conditional: if/else
521
531
  if (headStr === 'if') {
522
- return this.emitConditional(sexpr);
532
+ return this.generateConditional(sexpr);
523
533
  }
524
534
 
525
535
  // For loop
526
536
  if (headStr === 'for' || headStr === 'for-in' || headStr === 'for-of' || headStr === 'for-as') {
527
- return this.emitLoop(sexpr);
537
+ return this.generateTemplateLoop(sexpr);
528
538
  }
529
539
 
530
540
  // General expression (computed value, function call, binary op, etc.)
531
541
  const textVar = this.newTextVar();
532
542
  const exprCode = this.generateInComponent(sexpr, 'value');
533
543
  if (this.hasReactiveDeps(sexpr)) {
534
- this._emitCreateLines.push(`${textVar} = document.createTextNode('');`);
535
- this._emitSetupLines.push(`__effect(() => { ${textVar}.data = ${exprCode}; });`);
544
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
545
+ this._setupLines.push(`__effect(() => { ${textVar}.data = ${exprCode}; });`);
536
546
  } else {
537
- this._emitCreateLines.push(`${textVar} = document.createTextNode(String(${exprCode}));`);
547
+ this._createLines.push(`${textVar} = document.createTextNode(String(${exprCode}));`);
538
548
  }
539
549
  return textVar;
540
550
  };
541
551
 
542
552
  // --------------------------------------------------------------------------
543
- // emitTag — HTML element with static classes and children
553
+ // generateTag — HTML element with static classes and children
544
554
  // --------------------------------------------------------------------------
545
555
 
546
- proto.emitTag = function(tag, classes, args) {
556
+ proto.generateTag = function(tag, classes, args) {
547
557
  const elVar = this.newElementVar();
548
- this._emitCreateLines.push(`${elVar} = document.createElement('${tag}');`);
558
+ this._createLines.push(`${elVar} = document.createElement('${tag}');`);
549
559
 
550
560
  if (classes.length > 0) {
551
- this._emitCreateLines.push(`${elVar}.className = '${classes.join(' ')}';`);
561
+ this._createLines.push(`${elVar}.className = '${classes.join(' ')}';`);
552
562
  }
553
563
 
554
564
  for (const arg of args) {
@@ -557,51 +567,51 @@ export function installComponentSupport(CodeGenerator) {
557
567
  const block = arg[2];
558
568
  if (Array.isArray(block) && block[0] === 'block') {
559
569
  for (const child of block.slice(1)) {
560
- const childVar = this.emitNode(child);
561
- this._emitCreateLines.push(`${elVar}.appendChild(${childVar});`);
570
+ const childVar = this.generateNode(child);
571
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
562
572
  }
563
573
  } else if (block) {
564
- const childVar = this.emitNode(block);
565
- this._emitCreateLines.push(`${elVar}.appendChild(${childVar});`);
574
+ const childVar = this.generateNode(block);
575
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
566
576
  }
567
577
  }
568
578
  // Object = attributes/events
569
579
  else if (Array.isArray(arg) && arg[0] === 'object') {
570
- this.emitAttributes(elVar, arg);
580
+ this.generateAttributes(elVar, arg);
571
581
  }
572
582
  // String = text child
573
583
  else if (typeof arg === 'string') {
574
584
  const textVar = this.newTextVar();
575
585
  if (arg.startsWith('"') || arg.startsWith("'") || arg.startsWith('`')) {
576
- this._emitCreateLines.push(`${textVar} = document.createTextNode(${arg});`);
586
+ this._createLines.push(`${textVar} = document.createTextNode(${arg});`);
577
587
  } else if (this.reactiveMembers && this.reactiveMembers.has(arg)) {
578
- this._emitCreateLines.push(`${textVar} = document.createTextNode('');`);
579
- this._emitSetupLines.push(`__effect(() => { ${textVar}.data = this.${arg}.value; });`);
588
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
589
+ this._setupLines.push(`__effect(() => { ${textVar}.data = this.${arg}.value; });`);
580
590
  } else if (this.componentMembers && this.componentMembers.has(arg)) {
581
- this._emitCreateLines.push(`${textVar} = document.createTextNode(String(this.${arg}));`);
591
+ this._createLines.push(`${textVar} = document.createTextNode(String(this.${arg}));`);
582
592
  } else {
583
- this._emitCreateLines.push(`${textVar} = document.createTextNode(String(${arg}));`);
593
+ this._createLines.push(`${textVar} = document.createTextNode(String(${arg}));`);
584
594
  }
585
- this._emitCreateLines.push(`${elVar}.appendChild(${textVar});`);
595
+ this._createLines.push(`${elVar}.appendChild(${textVar});`);
586
596
  }
587
597
  // String object (from parser)
588
598
  else if (arg instanceof String) {
589
599
  const val = arg.valueOf();
590
600
  const textVar = this.newTextVar();
591
601
  if (val.startsWith('"') || val.startsWith("'") || val.startsWith('`')) {
592
- this._emitCreateLines.push(`${textVar} = document.createTextNode(${val});`);
602
+ this._createLines.push(`${textVar} = document.createTextNode(${val});`);
593
603
  } else if (this.reactiveMembers && this.reactiveMembers.has(val)) {
594
- this._emitCreateLines.push(`${textVar} = document.createTextNode('');`);
595
- this._emitSetupLines.push(`__effect(() => { ${textVar}.data = this.${val}.value; });`);
604
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
605
+ this._setupLines.push(`__effect(() => { ${textVar}.data = this.${val}.value; });`);
596
606
  } else {
597
- this._emitCreateLines.push(`${textVar} = document.createTextNode(String(${val}));`);
607
+ this._createLines.push(`${textVar} = document.createTextNode(String(${val}));`);
598
608
  }
599
- this._emitCreateLines.push(`${elVar}.appendChild(${textVar});`);
609
+ this._createLines.push(`${elVar}.appendChild(${textVar});`);
600
610
  }
601
611
  // Other = nested element
602
612
  else if (arg) {
603
- const childVar = this.emitNode(arg);
604
- this._emitCreateLines.push(`${elVar}.appendChild(${childVar});`);
613
+ const childVar = this.generateNode(arg);
614
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
605
615
  }
606
616
  }
607
617
 
@@ -609,20 +619,20 @@ export function installComponentSupport(CodeGenerator) {
609
619
  };
610
620
 
611
621
  // --------------------------------------------------------------------------
612
- // emitDynamicTag — tag with .() CLSX dynamic classes
622
+ // generateDynamicTag — tag with .() CLSX dynamic classes
613
623
  // --------------------------------------------------------------------------
614
624
 
615
- proto.emitDynamicTag = function(tag, classExprs, children) {
625
+ proto.generateDynamicTag = function(tag, classExprs, children) {
616
626
  const elVar = this.newElementVar();
617
- this._emitCreateLines.push(`${elVar} = document.createElement('${tag}');`);
627
+ this._createLines.push(`${elVar} = document.createElement('${tag}');`);
618
628
 
619
629
  if (classExprs.length > 0) {
620
630
  const classArgs = classExprs.map(e => this.generateInComponent(e, 'value')).join(', ');
621
631
  const hasReactive = classExprs.some(e => this.hasReactiveDeps(e));
622
632
  if (hasReactive) {
623
- this._emitSetupLines.push(`__effect(() => { ${elVar}.className = __cx__(${classArgs}); });`);
633
+ this._setupLines.push(`__effect(() => { ${elVar}.className = __cx__(${classArgs}); });`);
624
634
  } else {
625
- this._emitCreateLines.push(`${elVar}.className = __cx__(${classArgs});`);
635
+ this._createLines.push(`${elVar}.className = __cx__(${classArgs});`);
626
636
  }
627
637
  }
628
638
 
@@ -633,33 +643,33 @@ export function installComponentSupport(CodeGenerator) {
633
643
  const blockHead = Array.isArray(block) ? (block[0] instanceof String ? block[0].valueOf() : block[0]) : null;
634
644
  if (blockHead === 'block') {
635
645
  for (const child of block.slice(1)) {
636
- const childVar = this.emitNode(child);
637
- this._emitCreateLines.push(`${elVar}.appendChild(${childVar});`);
646
+ const childVar = this.generateNode(child);
647
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
638
648
  }
639
649
  } else if (block) {
640
- const childVar = this.emitNode(block);
641
- this._emitCreateLines.push(`${elVar}.appendChild(${childVar});`);
650
+ const childVar = this.generateNode(block);
651
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
642
652
  }
643
653
  }
644
654
  else if (Array.isArray(arg) && arg[0] === 'object') {
645
- this.emitAttributes(elVar, arg);
655
+ this.generateAttributes(elVar, arg);
646
656
  }
647
657
  else if (typeof arg === 'string' || arg instanceof String) {
648
658
  const textVar = this.newTextVar();
649
659
  const argStr = arg.valueOf();
650
660
  if (argStr.startsWith('"') || argStr.startsWith("'") || argStr.startsWith('`')) {
651
- this._emitCreateLines.push(`${textVar} = document.createTextNode(${argStr});`);
661
+ this._createLines.push(`${textVar} = document.createTextNode(${argStr});`);
652
662
  } else if (this.reactiveMembers && this.reactiveMembers.has(argStr)) {
653
- this._emitCreateLines.push(`${textVar} = document.createTextNode('');`);
654
- this._emitSetupLines.push(`__effect(() => { ${textVar}.data = this.${argStr}.value; });`);
663
+ this._createLines.push(`${textVar} = document.createTextNode('');`);
664
+ this._setupLines.push(`__effect(() => { ${textVar}.data = this.${argStr}.value; });`);
655
665
  } else {
656
- this._emitCreateLines.push(`${textVar} = document.createTextNode(${this.generateInComponent(arg, 'value')});`);
666
+ this._createLines.push(`${textVar} = document.createTextNode(${this.generateInComponent(arg, 'value')});`);
657
667
  }
658
- this._emitCreateLines.push(`${elVar}.appendChild(${textVar});`);
668
+ this._createLines.push(`${elVar}.appendChild(${textVar});`);
659
669
  }
660
670
  else {
661
- const childVar = this.emitNode(arg);
662
- this._emitCreateLines.push(`${elVar}.appendChild(${childVar});`);
671
+ const childVar = this.generateNode(arg);
672
+ this._createLines.push(`${elVar}.appendChild(${childVar});`);
663
673
  }
664
674
  }
665
675
 
@@ -667,10 +677,10 @@ export function installComponentSupport(CodeGenerator) {
667
677
  };
668
678
 
669
679
  // --------------------------------------------------------------------------
670
- // emitAttributes — attributes, events, and bindings on an element
680
+ // generateAttributes — attributes, events, and bindings on an element
671
681
  // --------------------------------------------------------------------------
672
682
 
673
- proto.emitAttributes = function(elVar, objExpr) {
683
+ proto.generateAttributes = function(elVar, objExpr) {
674
684
  const inputType = extractInputType(objExpr.slice(1));
675
685
 
676
686
  for (let i = 1; i < objExpr.length; i++) {
@@ -680,7 +690,7 @@ export function installComponentSupport(CodeGenerator) {
680
690
  if (Array.isArray(key) && key[0] === '.' && key[1] === 'this') {
681
691
  const eventName = key[2];
682
692
  const handlerCode = this.generateInComponent(value, 'value');
683
- this._emitCreateLines.push(`${elVar}.addEventListener('${eventName}', (e) => (${handlerCode})(e));`);
693
+ this._createLines.push(`${elVar}.addEventListener('${eventName}', (e) => (${handlerCode})(e));`);
684
694
  continue;
685
695
  }
686
696
 
@@ -706,8 +716,8 @@ export function installComponentSupport(CodeGenerator) {
706
716
  ? 'e.target.valueAsNumber' : 'e.target.value';
707
717
  }
708
718
 
709
- this._emitSetupLines.push(`__effect(() => { ${elVar}.${prop} = ${valueCode}; });`);
710
- this._emitCreateLines.push(`${elVar}.addEventListener('${event}', (e) => ${valueCode} = ${valueAccessor});`);
719
+ this._setupLines.push(`__effect(() => { ${elVar}.${prop} = ${valueCode}; });`);
720
+ this._createLines.push(`${elVar}.addEventListener('${event}', (e) => ${valueCode} = ${valueAccessor});`);
711
721
  continue;
712
722
  }
713
723
 
@@ -716,72 +726,72 @@ export function installComponentSupport(CodeGenerator) {
716
726
  // Smart two-way binding for value/checked when bound to reactive state
717
727
  if ((key === 'value' || key === 'checked') && this.hasReactiveDeps(value)) {
718
728
  // Reactive effect: signal → DOM property
719
- this._emitSetupLines.push(`__effect(() => { ${elVar}.${key} = ${valueCode}; });`);
729
+ this._setupLines.push(`__effect(() => { ${elVar}.${key} = ${valueCode}; });`);
720
730
  // Event listener: DOM → signal (two-way)
721
731
  const event = key === 'checked' ? 'change' : 'input';
722
732
  const accessor = key === 'checked' ? 'e.target.checked'
723
733
  : (inputType === 'number' || inputType === 'range') ? 'e.target.valueAsNumber'
724
734
  : 'e.target.value';
725
- this._emitCreateLines.push(`${elVar}.addEventListener('${event}', (e) => { ${valueCode} = ${accessor}; });`);
735
+ this._createLines.push(`${elVar}.addEventListener('${event}', (e) => { ${valueCode} = ${accessor}; });`);
726
736
  continue;
727
737
  }
728
738
 
729
739
  if (this.hasReactiveDeps(value)) {
730
- this._emitSetupLines.push(`__effect(() => { ${elVar}.setAttribute('${key}', ${valueCode}); });`);
740
+ this._setupLines.push(`__effect(() => { ${elVar}.setAttribute('${key}', ${valueCode}); });`);
731
741
  } else {
732
- this._emitCreateLines.push(`${elVar}.setAttribute('${key}', ${valueCode});`);
742
+ this._createLines.push(`${elVar}.setAttribute('${key}', ${valueCode});`);
733
743
  }
734
744
  }
735
745
  }
736
746
  };
737
747
 
738
748
  // --------------------------------------------------------------------------
739
- // emitBlock — a block of template children
749
+ // generateTemplateBlock — a block of template children
740
750
  // --------------------------------------------------------------------------
741
751
 
742
- proto.emitBlock = function(body) {
752
+ proto.generateTemplateBlock = function(body) {
743
753
  if (!Array.isArray(body) || body[0] !== 'block') {
744
- return this.emitNode(body);
754
+ return this.generateNode(body);
745
755
  }
746
756
 
747
757
  const statements = body.slice(1);
748
758
  if (statements.length === 0) {
749
759
  const commentVar = this.newElementVar('empty');
750
- this._emitCreateLines.push(`${commentVar} = document.createComment('');`);
760
+ this._createLines.push(`${commentVar} = document.createComment('');`);
751
761
  return commentVar;
752
762
  }
753
763
  if (statements.length === 1) {
754
- return this.emitNode(statements[0]);
764
+ return this.generateNode(statements[0]);
755
765
  }
756
766
 
757
767
  const fragVar = this.newElementVar('frag');
758
- this._emitCreateLines.push(`${fragVar} = document.createDocumentFragment();`);
768
+ this._createLines.push(`${fragVar} = document.createDocumentFragment();`);
759
769
  for (const stmt of statements) {
760
- const childVar = this.emitNode(stmt);
761
- this._emitCreateLines.push(`${fragVar}.appendChild(${childVar});`);
770
+ const childVar = this.generateNode(stmt);
771
+ this._createLines.push(`${fragVar}.appendChild(${childVar});`);
762
772
  }
763
773
  return fragVar;
764
774
  };
765
775
 
766
776
  // --------------------------------------------------------------------------
767
- // emitConditional — reactive if/else using block factories
777
+ // generateConditional — reactive if/else using block factories
768
778
  // --------------------------------------------------------------------------
769
779
 
770
- proto.emitConditional = function(sexpr) {
780
+ proto.generateConditional = function(sexpr) {
771
781
  const [, condition, thenBlock, elseBlock] = sexpr;
772
782
 
773
783
  const anchorVar = this.newElementVar('anchor');
774
- this._emitCreateLines.push(`${anchorVar} = document.createComment('if');`);
784
+ this._createLines.push(`${anchorVar} = document.createComment('if');`);
775
785
 
776
786
  const condCode = this.generateInComponent(condition, 'value');
777
787
 
778
788
  const thenBlockName = this.newBlockVar();
779
- this.emitConditionBranch(thenBlockName, thenBlock);
789
+ this.generateConditionBranch(thenBlockName, thenBlock);
780
790
 
781
791
  let elseBlockName = null;
782
792
  if (elseBlock) {
783
793
  elseBlockName = this.newBlockVar();
784
- this.emitConditionBranch(elseBlockName, elseBlock);
794
+ this.generateConditionBranch(elseBlockName, elseBlock);
785
795
  }
786
796
 
787
797
  const setupLines = [];
@@ -818,36 +828,30 @@ export function installComponentSupport(CodeGenerator) {
818
828
  setupLines.push(` });`);
819
829
  setupLines.push(`}`);
820
830
 
821
- this._emitSetupLines.push(setupLines.join('\n '));
831
+ this._setupLines.push(setupLines.join('\n '));
822
832
 
823
833
  return anchorVar;
824
834
  };
825
835
 
826
836
  // --------------------------------------------------------------------------
827
- // emitConditionBranch — block factory for a conditional branch
837
+ // generateConditionBranch — block factory for a conditional branch
828
838
  // --------------------------------------------------------------------------
829
839
 
830
- proto.emitConditionBranch = function(blockName, block) {
831
- const savedCreateLines = this._emitCreateLines;
832
- const savedSetupLines = this._emitSetupLines;
840
+ proto.generateConditionBranch = function(blockName, block) {
841
+ const savedCreateLines = this._createLines;
842
+ const savedSetupLines = this._setupLines;
833
843
 
834
- this._emitCreateLines = [];
835
- this._emitSetupLines = [];
844
+ this._createLines = [];
845
+ this._setupLines = [];
836
846
 
837
- const rootVar = this.emitBlock(block);
838
- const createLines = this._emitCreateLines;
839
- const setupLines = this._emitSetupLines;
847
+ const rootVar = this.generateTemplateBlock(block);
848
+ const createLines = this._createLines;
849
+ const setupLines = this._setupLines;
840
850
 
841
- this._emitCreateLines = savedCreateLines;
842
- this._emitSetupLines = savedSetupLines;
851
+ this._createLines = savedCreateLines;
852
+ this._setupLines = savedSetupLines;
843
853
 
844
- const localizeVar = (line) => {
845
- // First localize template element refs (this._elN → _elN)
846
- let result = line.replace(/this\.(_el\d+|_t\d+|_anchor\d+|_frag\d+|_slot\d+|_c\d+|_inst\d+|_empty\d+)/g, '$1');
847
- // Then replace remaining this. with ctx. (component instance in block context)
848
- result = result.replace(/\bthis\./g, 'ctx.');
849
- return result;
850
- };
854
+ const localizeVar = (line) => this.localizeVar(line);
851
855
 
852
856
  const factoryLines = [];
853
857
  factoryLines.push(`function ${blockName}(ctx) {`);
@@ -911,20 +915,20 @@ export function installComponentSupport(CodeGenerator) {
911
915
  factoryLines.push(` };`);
912
916
  factoryLines.push(`}`);
913
917
 
914
- this._emitBlockFactories.push(factoryLines.join('\n'));
918
+ this._blockFactories.push(factoryLines.join('\n'));
915
919
  };
916
920
 
917
921
  // --------------------------------------------------------------------------
918
- // emitLoop — reactive for-loop with keyed reconciliation
922
+ // generateTemplateLoop — reactive for-loop with keyed reconciliation
919
923
  // --------------------------------------------------------------------------
920
924
 
921
- proto.emitLoop = function(sexpr) {
925
+ proto.generateTemplateLoop = function(sexpr) {
922
926
  const [head, vars, collection, guard, step, body] = sexpr;
923
927
 
924
928
  const blockName = this.newBlockVar();
925
929
 
926
930
  const anchorVar = this.newElementVar('anchor');
927
- this._emitCreateLines.push(`${anchorVar} = document.createComment('for');`);
931
+ this._createLines.push(`${anchorVar} = document.createComment('for');`);
928
932
 
929
933
  const varNames = Array.isArray(vars) ? vars : [vars];
930
934
  const itemVar = varNames[0];
@@ -953,26 +957,20 @@ export function installComponentSupport(CodeGenerator) {
953
957
  }
954
958
 
955
959
  // Save state and generate item template in isolation
956
- const savedCreateLines = this._emitCreateLines;
957
- const savedSetupLines = this._emitSetupLines;
960
+ const savedCreateLines = this._createLines;
961
+ const savedSetupLines = this._setupLines;
958
962
 
959
- this._emitCreateLines = [];
960
- this._emitSetupLines = [];
963
+ this._createLines = [];
964
+ this._setupLines = [];
961
965
 
962
- const itemNode = this.emitBlock(body);
963
- const itemCreateLines = this._emitCreateLines;
964
- const itemSetupLines = this._emitSetupLines;
966
+ const itemNode = this.generateTemplateBlock(body);
967
+ const itemCreateLines = this._createLines;
968
+ const itemSetupLines = this._setupLines;
965
969
 
966
- this._emitCreateLines = savedCreateLines;
967
- this._emitSetupLines = savedSetupLines;
970
+ this._createLines = savedCreateLines;
971
+ this._setupLines = savedSetupLines;
968
972
 
969
- const localizeVar = (line) => {
970
- // First localize template element refs (this._elN → _elN)
971
- let result = line.replace(/this\.(_el\d+|_t\d+|_anchor\d+|_frag\d+|_slot\d+|_c\d+|_inst\d+|_empty\d+)/g, '$1');
972
- // Then replace remaining this. with ctx. (component instance in block context)
973
- result = result.replace(/\bthis\./g, 'ctx.');
974
- return result;
975
- };
973
+ const localizeVar = (line) => this.localizeVar(line);
976
974
 
977
975
  // Generate block factory
978
976
  const factoryLines = [];
@@ -1036,7 +1034,7 @@ export function installComponentSupport(CodeGenerator) {
1036
1034
  factoryLines.push(` };`);
1037
1035
  factoryLines.push(`}`);
1038
1036
 
1039
- this._emitBlockFactories.push(factoryLines.join('\n'));
1037
+ this._blockFactories.push(factoryLines.join('\n'));
1040
1038
 
1041
1039
  // Generate reconciliation code in _setup()
1042
1040
  const setupLines = [];
@@ -1073,27 +1071,27 @@ export function installComponentSupport(CodeGenerator) {
1073
1071
  setupLines.push(` });`);
1074
1072
  setupLines.push(`}`);
1075
1073
 
1076
- this._emitSetupLines.push(setupLines.join('\n '));
1074
+ this._setupLines.push(setupLines.join('\n '));
1077
1075
 
1078
1076
  return anchorVar;
1079
1077
  };
1080
1078
 
1081
1079
  // --------------------------------------------------------------------------
1082
- // emitChildComponent — instantiate a child component
1080
+ // generateChildComponent — instantiate a child component
1083
1081
  // --------------------------------------------------------------------------
1084
1082
 
1085
- proto.emitChildComponent = function(componentName, args) {
1083
+ proto.generateChildComponent = function(componentName, args) {
1086
1084
  const instVar = this.newElementVar('inst');
1087
1085
  const elVar = this.newElementVar('el');
1088
1086
  const { propsCode, childrenSetupLines } = this.buildComponentProps(args);
1089
1087
 
1090
- this._emitCreateLines.push(`${instVar} = new ${componentName}(${propsCode});`);
1091
- this._emitCreateLines.push(`${elVar} = ${instVar}._create();`);
1088
+ this._createLines.push(`${instVar} = new ${componentName}(${propsCode});`);
1089
+ this._createLines.push(`${elVar} = ${instVar}._create();`);
1092
1090
 
1093
- this._emitSetupLines.push(`if (${instVar}._setup) ${instVar}._setup();`);
1091
+ this._setupLines.push(`if (${instVar}._setup) ${instVar}._setup();`);
1094
1092
 
1095
1093
  for (const line of childrenSetupLines) {
1096
- this._emitSetupLines.push(line);
1094
+ this._setupLines.push(line);
1097
1095
  }
1098
1096
 
1099
1097
  return elVar;
@@ -1120,21 +1118,21 @@ export function installComponentSupport(CodeGenerator) {
1120
1118
  } else if (Array.isArray(arg) && (arg[0] === '->' || arg[0] === '=>')) {
1121
1119
  const block = arg[2];
1122
1120
  if (block) {
1123
- const savedCreateLines = this._emitCreateLines;
1124
- const savedSetupLines = this._emitSetupLines;
1125
- this._emitCreateLines = [];
1126
- this._emitSetupLines = [];
1121
+ const savedCreateLines = this._createLines;
1122
+ const savedSetupLines = this._setupLines;
1123
+ this._createLines = [];
1124
+ this._setupLines = [];
1127
1125
 
1128
- childrenVar = this.emitBlock(block);
1126
+ childrenVar = this.generateTemplateBlock(block);
1129
1127
 
1130
- const childCreateLines = this._emitCreateLines;
1131
- const childSetupLinesCopy = this._emitSetupLines;
1128
+ const childCreateLines = this._createLines;
1129
+ const childSetupLinesCopy = this._setupLines;
1132
1130
 
1133
- this._emitCreateLines = savedCreateLines;
1134
- this._emitSetupLines = savedSetupLines;
1131
+ this._createLines = savedCreateLines;
1132
+ this._setupLines = savedSetupLines;
1135
1133
 
1136
1134
  for (const line of childCreateLines) {
1137
- this._emitCreateLines.push(line);
1135
+ this._createLines.push(line);
1138
1136
  }
1139
1137
  childrenSetupLines.push(...childSetupLinesCopy);
1140
1138
  props.push(`children: ${childrenVar}`);