rip-lang 3.13.32 → 3.13.34

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.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rip-lang",
3
- "version": "3.13.32",
3
+ "version": "3.13.34",
4
4
  "description": "A modern language that compiles to JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
package/src/components.js CHANGED
@@ -528,25 +528,36 @@ export function installComponentSupport(CodeGenerator, Lexer) {
528
528
  * Recursively transform s-expression to replace member identifiers with this.X.value.
529
529
  * For component context where state variables are signals.
530
530
  */
531
+ const _str = (s) => typeof s === 'string' ? s : s instanceof String ? s.valueOf() : null;
532
+ const _transferMeta = (from, to) => {
533
+ if (!(from instanceof String)) return to;
534
+ const s = new String(to);
535
+ if (from.predicate) s.predicate = true;
536
+ if (from.await) s.await = true;
537
+ return (s.predicate || s.await) ? s : to;
538
+ };
539
+
531
540
  proto.transformComponentMembers = function(sexpr) {
532
541
  const self = this._self;
533
542
  if (!Array.isArray(sexpr)) {
534
- if (typeof sexpr === 'string' && this.reactiveMembers && this.reactiveMembers.has(sexpr)) {
535
- return ['.', ['.', self, sexpr], 'value'];
543
+ const sv = _str(sexpr);
544
+ if (sv && this.reactiveMembers && this.reactiveMembers.has(sv)) {
545
+ return ['.', ['.', self, sv], _transferMeta(sexpr, 'value')];
536
546
  }
537
- if (typeof sexpr === 'string' && this.componentMembers && this.componentMembers.has(sexpr)) {
538
- return ['.', self, sexpr];
547
+ if (sv && this.componentMembers && this.componentMembers.has(sv)) {
548
+ return ['.', self, _transferMeta(sexpr, sv)];
539
549
  }
540
550
  return sexpr;
541
551
  }
542
552
 
543
553
  // Special case: (. this memberName) for @member syntax
544
- if (sexpr[0] === '.' && sexpr[1] === 'this' && typeof sexpr[2] === 'string') {
545
- const memberName = sexpr[2];
554
+ if (sexpr[0] === '.' && sexpr[1] === 'this' && _str(sexpr[2]) != null) {
555
+ const prop = sexpr[2];
556
+ const memberName = _str(prop);
546
557
  if (this.reactiveMembers && this.reactiveMembers.has(memberName)) {
547
- return ['.', ['.', self, memberName], 'value'];
558
+ return ['.', ['.', self, memberName], _transferMeta(prop, 'value')];
548
559
  }
549
- return this._factoryMode ? ['.', self, sexpr[2]] : sexpr;
560
+ return this._factoryMode ? ['.', self, prop] : sexpr;
550
561
  }
551
562
 
552
563
  // Dot access: transform the object but not the property name
@@ -706,7 +717,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
706
717
 
707
718
  // Computed (derived)
708
719
  for (const { name, expr } of derivedVars) {
709
- if (this.is(expr, 'block') && expr.length > 2) {
720
+ if (this.is(expr, 'block')) {
710
721
  const transformed = this.transformComponentMembers(expr);
711
722
  const body = this.generateFunctionBody(transformed);
712
723
  lines.push(` this.${name} = __computed(() => ${body});`);
@@ -720,7 +731,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
720
731
  for (const effect of effects) {
721
732
  const effectBody = effect[2];
722
733
  const isAsync = this.containsAwait(effectBody) ? 'async ' : '';
723
- if (this.is(effectBody, 'block') && effectBody.length > 2) {
734
+ if (this.is(effectBody, 'block')) {
724
735
  const transformed = this.transformComponentMembers(effectBody);
725
736
  const body = this.generateFunctionBody(transformed, [], true);
726
737
  lines.push(` __effect(${isAsync}() => ${body});`);
@@ -925,6 +936,13 @@ export function installComponentSupport(CodeGenerator, Lexer) {
925
936
  this._pushEffect(`${textVar}.data = ${this._self}.${str}.value;`);
926
937
  return textVar;
927
938
  }
939
+ // Slot projection — bare <slot> tag → project @children
940
+ if (str === 'slot' && this.componentMembers) {
941
+ const s = this._self;
942
+ const slotVar = this.newElementVar('slot');
943
+ this._createLines.push(`${slotVar} = ${s}.children instanceof Node ? ${s}.children : (${s}.children != null ? document.createTextNode(String(${s}.children)) : document.createComment(''));`);
944
+ return slotVar;
945
+ }
928
946
  // Static tag without content (possibly with #id)
929
947
  const [tagStr, idStr] = str.split('#');
930
948
  const elVar = this.newElementVar();
@@ -1344,7 +1362,11 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1344
1362
  this._createLines.push(`if (${valueCode}) ${elVar}.setAttribute('${key}', '');`);
1345
1363
  }
1346
1364
  } else if (this.hasReactiveDeps(value)) {
1347
- this._pushEffect(`${elVar}.setAttribute('${key}', ${valueCode});`);
1365
+ if (Array.isArray(value) && value[0] === 'presence') {
1366
+ this._pushEffect(`{ const __v = ${valueCode}; __v == null ? ${elVar}.removeAttribute('${key}') : ${elVar}.setAttribute('${key}', __v); }`);
1367
+ } else {
1368
+ this._pushEffect(`${elVar}.setAttribute('${key}', ${valueCode});`);
1369
+ }
1348
1370
  } else {
1349
1371
  this._createLines.push(`${elVar}.setAttribute('${key}', ${valueCode});`);
1350
1372
  }