rip-lang 3.12.4 → 3.13.0

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.12.4",
3
+ "version": "3.13.0",
4
4
  "description": "A modern language that compiles to JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
package/src/app.rip CHANGED
@@ -661,6 +661,7 @@ export createRenderer = (opts = {}) ->
661
661
 
662
662
  currentComponent = null
663
663
  currentRoute = null
664
+ currentParams = null
664
665
  currentLayouts = []
665
666
  layoutInstances = []
666
667
  mountPoint = container
@@ -688,7 +689,7 @@ export createRenderer = (opts = {}) ->
688
689
  for inst in layoutInstances by -1
689
690
  inst.beforeUnmount() if inst.beforeUnmount
690
691
  inst.unmounted() if inst.unmounted
691
- inst._root?.remove()
692
+ inst._target?.remove()
692
693
  layoutInstances = []
693
694
  mountPoint = container
694
695
 
@@ -702,7 +703,9 @@ export createRenderer = (opts = {}) ->
702
703
  mountRoute = (info) ->
703
704
  { route, params, layouts: layoutFiles, query } = info
704
705
  return unless route
705
- return if route.file is currentRoute # already showing this route
706
+ if route.file is currentRoute and JSON.stringify(params) is JSON.stringify(currentParams)
707
+ return
708
+ currentParams = params
706
709
 
707
710
  gen = ++generation
708
711
  router.navigating = true
@@ -724,7 +727,7 @@ export createRenderer = (opts = {}) ->
724
727
  return
725
728
 
726
729
  layoutsChanged = not arraysEqual(layoutFiles, currentLayouts)
727
- oldRoot = currentComponent?._root
730
+ oldTarget = currentComponent?._target
728
731
 
729
732
  if layoutsChanged
730
733
  unmount()
@@ -768,7 +771,7 @@ export createRenderer = (opts = {}) ->
768
771
  cached = componentCache.get(route.file)
769
772
  if cached
770
773
  componentCache.delete route.file
771
- mp.appendChild cached._root
774
+ mp.appendChild cached._target
772
775
  currentComponent = cached
773
776
  currentRoute = route.file
774
777
  else
@@ -783,7 +786,7 @@ export createRenderer = (opts = {}) ->
783
786
  currentRoute = route.file
784
787
 
785
788
  instance.load!(params, query) if instance.load
786
- oldRoot?.remove()
789
+ oldTarget?.remove()
787
790
  router.navigating = false
788
791
  if container.style.opacity is '0'
789
792
  document.fonts.ready.then ->
@@ -857,6 +860,12 @@ connectWatch = (url) ->
857
860
  console.log '[Rip] Reloading...'
858
861
  location.reload()
859
862
 
863
+ es.addEventListener 'css', ->
864
+ for link as document.querySelectorAll('link[rel="stylesheet"]')
865
+ url = new URL(link.href)
866
+ url.searchParams.set('_t', Date.now())
867
+ link.href = url.toString()
868
+
860
869
  es.onerror = ->
861
870
  es.close()
862
871
  setTimeout connect, retryDelay
package/src/compiler.js CHANGED
@@ -637,8 +637,26 @@ export class CodeGenerator {
637
637
  let skip = this.options.skipPreamble;
638
638
 
639
639
  if (!skip) {
640
- if (this.helpers.has('slice')) { code += 'const slice = [].slice;\n'; needsBlank = true; }
641
- if (this.helpers.has('modulo')) { code += 'const modulo = (n, d) => { n = +n; d = +d; return (n % d + d) % d; };\n'; needsBlank = true; }
640
+
641
+ // Standard library always available, override by redeclaring
642
+ if (needsBlank) code += '\n';
643
+ code += 'globalThis.abort ??= (msg) => { if (msg) console.error(msg); process.exit(1); };\n';
644
+ code += 'globalThis.assert ??= (v, msg) => { if (!v) throw new Error(msg || "Assertion failed"); };\n';
645
+ code += 'globalThis.exit ??= (code) => process.exit(code || 0);\n';
646
+ code += 'globalThis.kind ??= (v) => v != null ? (v.constructor?.name || Object.prototype.toString.call(v).slice(8, -1)).toLowerCase() : String(v);\n';
647
+ code += 'globalThis.noop ??= () => {};\n';
648
+ code += 'globalThis.p ??= console.log;\n';
649
+ code += 'globalThis.pp ??= (v) => { console.log(JSON.stringify(v, null, 2)); return v; };\n';
650
+ code += 'globalThis.raise ??= (a, b) => { throw (b !== undefined ? new a(b) : new Error(a)); };\n';
651
+ code += 'globalThis.rand ??= (a, b) => b !== undefined ? (a > b && ([a, b] = [b, a]), Math.floor(Math.random() * (b - a + 1) + a)) : a ? Math.floor(Math.random() * a) : Math.random();\n';
652
+ code += 'globalThis.sleep ??= (ms) => new Promise(r => setTimeout(r, ms));\n';
653
+ code += 'globalThis.todo ??= (msg) => { throw new Error(msg || "Not implemented"); };\n';
654
+ code += 'globalThis.warn ??= console.warn;\n';
655
+ code += 'globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));\n';
656
+ needsBlank = true;
657
+
658
+ if (this.helpers.has('slice' )) { code += 'const slice = [].slice;\n'; needsBlank = true; }
659
+ if (this.helpers.has('modulo' )) { code += 'const modulo = (n, d) => { n = +n; d = +d; return (n % d + d) % d; };\n'; needsBlank = true; }
642
660
  if (this.helpers.has('toMatchable')) {
643
661
  code += 'const toMatchable = (v, allowNewlines) => {\n';
644
662
  code += ' if (typeof v === "string") return !allowNewlines && /[\\n\\r]/.test(v) ? null : v;\n';
package/src/components.js CHANGED
@@ -729,13 +729,14 @@ export function installComponentSupport(CodeGenerator, Lexer) {
729
729
  // Effects
730
730
  for (const effect of effects) {
731
731
  const effectBody = effect[2];
732
+ const isAsync = this.containsAwait(effectBody) ? 'async ' : '';
732
733
  if (this.is(effectBody, 'block') && effectBody.length > 2) {
733
734
  const transformed = this.transformComponentMembers(effectBody);
734
735
  const body = this.generateFunctionBody(transformed, [], true);
735
- lines.push(` __effect(() => ${body});`);
736
+ lines.push(` __effect(${isAsync}() => ${body});`);
736
737
  } else {
737
738
  const effectCode = this.generateInComponent(effectBody, 'value');
738
- lines.push(` __effect(() => { ${effectCode}; });`);
739
+ lines.push(` __effect(${isAsync}() => { ${effectCode}; });`);
739
740
  }
740
741
  }
741
742
 
package/src/typecheck.js CHANGED
@@ -206,6 +206,25 @@ export function compileForCheck(filePath, source, compiler) {
206
206
  }
207
207
  }
208
208
 
209
+ // Interpolate gaps — if src line A maps to gen line X and src line B maps to
210
+ // gen line Y, fill src lines A+1..B-1 → gen lines X+1..Y-1. This gives hover
211
+ // and diagnostics coverage for function body lines that the compiler didn't map.
212
+ const mapped = [...srcToGen.entries()].sort((a, b) => a[0] - b[0]);
213
+ for (let i = 0; i < mapped.length - 1; i++) {
214
+ const [srcA, genA] = mapped[i];
215
+ const [srcB, genB] = mapped[i + 1];
216
+ const srcGap = srcB - srcA;
217
+ const genGap = genB - genA;
218
+ if (srcGap > 1 && genGap > 1 && srcGap <= genGap + 2) {
219
+ for (let d = 1; d < srcGap; d++) {
220
+ if (!srcToGen.has(srcA + d) && genA + d < genB) {
221
+ srcToGen.set(srcA + d, genA + d);
222
+ genToSrc.set(genA + d, srcA + d);
223
+ }
224
+ }
225
+ }
226
+ }
227
+
209
228
  return { tsContent, headerLines, hasTypes, srcToGen, genToSrc, source };
210
229
  }
211
230