@vesk/compiler 0.2.60 → 0.2.61

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.
@@ -1 +1 @@
1
- {"version":3,"file":"client-codegen.d.ts","sourceRoot":"","sources":["../src/client-codegen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAGL,cAAc,EAQd,gBAAgB,EASjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAkGxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1D;AAiDD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAgJlI;AAID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAU5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,EAAE,CAuB9F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAY5F;AAoBD,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,SAAS,CAQtE;AA0iED,iBAAS,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAe3C;AAmJD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9C;AAuED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAOpQ;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,UAAU,CAAC,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAyC5J;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/E;AAED,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"client-codegen.d.ts","sourceRoot":"","sources":["../src/client-codegen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAGL,cAAc,EAQd,gBAAgB,EAUjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAkGxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1D;AAiDD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAgJlI;AAID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAI5E;AAyCD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,EAAE,CAuB9F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAY5F;AAoBD,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,SAAS,CAQtE;AAumED,iBAAS,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAe3C;AAmJD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9C;AAuED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAOpQ;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,UAAU,CAAC,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAyC5J;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/E;AAED,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -2,7 +2,7 @@ import { walk } from 'zimmerframe';
2
2
  import { print } from 'esrap';
3
3
  import ts from 'esrap/languages/ts';
4
4
  import tsx from 'esrap/languages/tsx';
5
- import { StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, ForLoop, TrackDecl, RuntimeStatement, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
5
+ import { StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, ForLoop, TrackDecl, RuntimeStatement, BreakSignal, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
6
6
  import { parse } from '@vesk/compiler/src/parser';
7
7
  import { generateIR } from '@vesk/compiler/src/ir-generator';
8
8
  import { transformTopLevelForActions } from '@vesk/compiler/src/actions';
@@ -296,6 +296,20 @@ export function transformTracked(irNode, tracked) {
296
296
  }
297
297
  export function collectTrackedNames(body) {
298
298
  const names = new Map();
299
+ collectTrackedNamesInto(body, names);
300
+ return names;
301
+ }
302
+ /**
303
+ * A `track()` declaration is not always a direct child of the component body.
304
+ * A guard-clause early return (`if (!props.x) return <empty/>;`) lowers to an
305
+ * opaque region whose alternate branch carries the rest of the body — so the
306
+ * track decls (and every assignment that must become `set(cell, …)`) live
307
+ * inside `OpaqueDynamicRegion.alternateNodes`, not at the top level. Other
308
+ * constructs (loops, switch cases, `{#server}` blocks, slot children) nest
309
+ * bodies too. Miss one and the cell is emitted but never `get`/`set`-wrapped,
310
+ * which both breaks reactivity and leaves `x = …` assigning to a `const`.
311
+ */
312
+ function collectTrackedNamesInto(body, names) {
299
313
  for (const node of body) {
300
314
  if (node instanceof TrackDecl) {
301
315
  const cellName = node.rawName || node.name;
@@ -303,8 +317,35 @@ export function collectTrackedNames(body) {
303
317
  if (node.rawName)
304
318
  names.set(node.rawName, { cellName, kind: 'cell' });
305
319
  }
320
+ else if (node instanceof StaticNode || node instanceof ServerBlock || node instanceof ClientBlock || node instanceof HeadBlock) {
321
+ collectTrackedNamesInto(node.children, names);
322
+ }
323
+ else if (node instanceof ComponentCall) {
324
+ collectTrackedNamesInto(node.children, names);
325
+ }
326
+ else if (node instanceof PropSlot) {
327
+ collectTrackedNamesInto(node.body, names);
328
+ }
329
+ else if (node instanceof MapRegion) {
330
+ collectTrackedNamesInto(node.bodyTemplate, names);
331
+ collectTrackedNamesInto(node.alternateNodes, names);
332
+ }
333
+ else if (node instanceof OpaqueDynamicRegion) {
334
+ collectTrackedNamesInto(node.consequentNodes, names);
335
+ collectTrackedNamesInto(node.alternateNodes, names);
336
+ }
337
+ else if (node instanceof WhileLoop || node instanceof ForLoop) {
338
+ collectTrackedNamesInto(node.bodyTemplate, names);
339
+ }
340
+ else if (node instanceof TryCatch) {
341
+ collectTrackedNamesInto(node.bodyTemplate, names);
342
+ collectTrackedNamesInto(node.catchBody, names);
343
+ }
344
+ else if (node instanceof SwitchBlock) {
345
+ for (const c of node.cases)
346
+ collectTrackedNamesInto(c.body, names);
347
+ }
306
348
  }
307
- return names;
308
349
  }
309
350
  /**
310
351
  * Collect the tracked bindings a prop expression READS, so a string-returning
@@ -428,6 +469,9 @@ class Ctx {
428
469
  walker = '__hydrate';
429
470
  asyncComps = new Set();
430
471
  isAsyncScope = false;
472
+ // While emitting a loop body, names the boolean flag a `break` sets (see
473
+ // BreakSignal). Null outside a break-capable loop body.
474
+ breakFlag = null;
431
475
  constructor(alloc) {
432
476
  this.alloc = alloc ?? { c: 0 };
433
477
  }
@@ -516,6 +560,11 @@ function emitNode(ctx, node, tracked, effectsVar, parentVar, compPrefix = '__com
516
560
  ctx.push(semicolonizeStatement(transformTracked(node, tracked)));
517
561
  return null;
518
562
  }
563
+ if (node instanceof BreakSignal) {
564
+ if (ctx.breakFlag)
565
+ ctx.push(`${ctx.breakFlag} = true;`);
566
+ return null;
567
+ }
519
568
  if (node instanceof SlotNode) {
520
569
  if (!parentVar) {
521
570
  // A TOP-LEVEL `{props.children}` — the whole body of a layout is one
@@ -1749,6 +1798,8 @@ function emitWhileLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1749
1798
  ctx.push(`const ${endAnchor} = document.createComment('while-end');`);
1750
1799
  emitHydrateFenceAnchoring(ctx, anchor, endAnchor, parent === '$root', budget || undefined);
1751
1800
  const renderLoop = ctx.n();
1801
+ const hasBreak = bodyHasBreak(node.bodyTemplate);
1802
+ const breakVar = hasBreak ? ctx.n() : null;
1752
1803
  ctx.push(`const ${renderLoop} = ${ctx.isAsyncScope ? 'async () => {' : '() => {'}`);
1753
1804
  if (!hyd)
1754
1805
  ctx.push(indent(`const __p = ${anchor}.parentNode;`));
@@ -1756,8 +1807,14 @@ function emitWhileLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1756
1807
  ctx.push(indent(`const __b = document.createDocumentFragment();`));
1757
1808
  if (hyd)
1758
1809
  ctx.push(indent(`const __cl = [];`));
1810
+ if (breakVar)
1811
+ ctx.push(indent(`let ${breakVar} = false;`));
1812
+ const savedBreakFlag = ctx.breakFlag;
1813
+ ctx.breakFlag = breakVar;
1759
1814
  if (node.isDoWhile) {
1760
1815
  ctx.push(indent(`do {`));
1816
+ if (breakVar)
1817
+ ctx.push(indent(indent(`if (${breakVar}) break;`)));
1761
1818
  for (const n of node.bodyTemplate) {
1762
1819
  const v = emitNode(ctx, n, tracked, effectsVar, hyd ? parentVar : '__b', '__components', 0, budget || undefined);
1763
1820
  if (v) {
@@ -1771,6 +1828,8 @@ function emitWhileLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1771
1828
  }
1772
1829
  else {
1773
1830
  ctx.push(indent(`while (${condExpr}) {`));
1831
+ if (breakVar)
1832
+ ctx.push(indent(indent(`if (${breakVar}) break;`)));
1774
1833
  for (const n of node.bodyTemplate) {
1775
1834
  const v = emitNode(ctx, n, tracked, effectsVar, hyd ? parentVar : '__b', '__components', 0, budget || undefined);
1776
1835
  if (v) {
@@ -1782,6 +1841,7 @@ function emitWhileLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1782
1841
  }
1783
1842
  ctx.push(indent(`}`));
1784
1843
  }
1844
+ ctx.breakFlag = savedBreakFlag;
1785
1845
  if (!hyd)
1786
1846
  ctx.push(indent(`__p.insertBefore(__b, ${endAnchor});`));
1787
1847
  if (hyd)
@@ -1825,6 +1885,8 @@ function emitForLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1825
1885
  ctx.push(`const ${endAnchor} = document.createComment('for-end');`);
1826
1886
  emitHydrateFenceAnchoring(ctx, anchor, endAnchor, parent === '$root', budget || undefined);
1827
1887
  const renderLoop = ctx.n();
1888
+ const forHasBreak = bodyHasBreak(node.bodyTemplate);
1889
+ const forBreakVar = forHasBreak ? ctx.n() : null;
1828
1890
  ctx.push(`const ${renderLoop} = ${ctx.isAsyncScope ? 'async () => {' : '() => {'}`);
1829
1891
  if (!hyd)
1830
1892
  ctx.push(indent(`const __p = ${anchor}.parentNode;`));
@@ -1832,9 +1894,15 @@ function emitForLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1832
1894
  ctx.push(indent(`const __b = document.createDocumentFragment();`));
1833
1895
  if (hyd)
1834
1896
  ctx.push(indent(`const __cl = [];`));
1897
+ if (forBreakVar)
1898
+ ctx.push(indent(`let ${forBreakVar} = false;`));
1899
+ const savedForBreakFlag = ctx.breakFlag;
1900
+ ctx.breakFlag = forBreakVar;
1835
1901
  if (node.kind === 'for-in') {
1836
1902
  const srcExpr = transformTracked(node.condition, tracked);
1837
1903
  ctx.push(indent(`for (${node.init} of (Array.isArray(${srcExpr}) ? ${srcExpr} : (${srcExpr} == null ? [] : Object.keys(${srcExpr})))) {`));
1904
+ if (forBreakVar)
1905
+ ctx.push(indent(indent(`if (${forBreakVar}) break;`)));
1838
1906
  for (const n of node.bodyTemplate) {
1839
1907
  const v = emitNode(ctx, n, tracked, effectsVar, hyd ? parentVar : '__b', '__components', 0, budget || undefined);
1840
1908
  if (v) {
@@ -1864,6 +1932,8 @@ function emitForLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1864
1932
  updatePart = updatePart.slice(0, -1).trim();
1865
1933
  const head = initPart ? `${initPart}; ${condExpr}` : `; ${condExpr}`;
1866
1934
  ctx.push(indent(`for (${head}; ${updatePart}) {`));
1935
+ if (forBreakVar)
1936
+ ctx.push(indent(indent(`if (${forBreakVar}) break;`)));
1867
1937
  for (const n of node.bodyTemplate) {
1868
1938
  const v = emitNode(ctx, n, tracked, effectsVar, hyd ? parentVar : '__b', '__components', 0, budget || undefined);
1869
1939
  if (v) {
@@ -1875,6 +1945,7 @@ function emitForLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
1875
1945
  }
1876
1946
  ctx.push(indent(`}`));
1877
1947
  }
1948
+ ctx.breakFlag = savedForBreakFlag;
1878
1949
  if (!hyd)
1879
1950
  ctx.push(indent(`__p.insertBefore(__b, ${endAnchor});`));
1880
1951
  if (hyd)
@@ -2060,6 +2131,47 @@ function emitSwitchBlock(ctx, node, tracked, parentVar, skipK = 0, regionBudget)
2060
2131
  }`);
2061
2132
  return null;
2062
2133
  }
2134
+ /**
2135
+ * True when a loop body contains a BreakSignal (or `continue`/`break`) that
2136
+ * targets the loop itself. Descent stops at nested loops, whose breaks bind to
2137
+ * themselves and are handled by their own emitter.
2138
+ */
2139
+ function bodyHasBreak(nodes) {
2140
+ for (const n of nodes) {
2141
+ if (n instanceof BreakSignal)
2142
+ return true;
2143
+ if (n instanceof OpaqueDynamicRegion) {
2144
+ if (bodyHasBreak([...n.consequentNodes, ...n.alternateNodes]))
2145
+ return true;
2146
+ }
2147
+ else if (n instanceof SwitchBlock) {
2148
+ for (const c of n.cases)
2149
+ if (bodyHasBreak(c.body))
2150
+ return true;
2151
+ }
2152
+ else if (n instanceof TryCatch) {
2153
+ if (bodyHasBreak([...n.bodyTemplate, ...n.catchBody]))
2154
+ return true;
2155
+ }
2156
+ else if (n instanceof StaticNode) {
2157
+ if (bodyHasBreak(n.children))
2158
+ return true;
2159
+ }
2160
+ else if (n instanceof ComponentCall) {
2161
+ if (bodyHasBreak(n.children))
2162
+ return true;
2163
+ }
2164
+ else if (n instanceof ServerBlock || n instanceof ClientBlock || n instanceof HeadBlock) {
2165
+ if (bodyHasBreak(n.children))
2166
+ return true;
2167
+ }
2168
+ else if (n instanceof PropSlot) {
2169
+ if (bodyHasBreak(n.body))
2170
+ return true;
2171
+ }
2172
+ }
2173
+ return false;
2174
+ }
2063
2175
  function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudget) {
2064
2176
  const arrExpr = transformTracked(node.expression, tracked);
2065
2177
  const itemVar = node.itemVariable;
@@ -2109,9 +2221,15 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
2109
2221
  ctx.push(`let ${effectsVar} = [];`);
2110
2222
  ctx.push(`const ${endAnchor} = document.createComment('map-end');`);
2111
2223
  const renderItem = ctx.n();
2224
+ const hasBreak = bodyHasBreak(node.bodyTemplate);
2225
+ const breakVar = hasBreak ? ctx.n() : null;
2226
+ if (breakVar)
2227
+ ctx.push(`let ${breakVar} = false;`);
2112
2228
  const indexParam = node.indexVariable ? ', __i' : '';
2113
2229
  ctx.push(`const ${renderItem} = ${ctx.isAsyncScope ? 'async ' : ''}(${itemVar}${indexParam}, __e, __r${hyd ? ', __cl' : ''}${hydKeyed ? ', __root' : ''}) => {`);
2114
2230
  ctx.push(indent(`__r = __r || ${endAnchor};`));
2231
+ if (breakVar)
2232
+ ctx.push(indent(`if (${breakVar}) return;`));
2115
2233
  if (node.indexVariable)
2116
2234
  ctx.push(indent(`const ${node.indexVariable} = __i;`));
2117
2235
  if (hyd) {
@@ -2128,6 +2246,8 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
2128
2246
  }
2129
2247
  if (hydKeyed)
2130
2248
  ctx.rootClaim = true;
2249
+ const savedMapBreak = ctx.breakFlag;
2250
+ ctx.breakFlag = breakVar;
2131
2251
  for (const n of node.bodyTemplate) {
2132
2252
  const v = emitNode(ctx, n, tracked, '__e', hyd ? undefined : '__it', '__components', 0, budget || undefined);
2133
2253
  if (v) {
@@ -2145,6 +2265,7 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
2145
2265
  }
2146
2266
  }
2147
2267
  }
2268
+ ctx.breakFlag = savedMapBreak;
2148
2269
  if (hydKeyed)
2149
2270
  ctx.rootClaim = false;
2150
2271
  if (!hyd)
@@ -2199,16 +2320,17 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
2199
2320
  const keyFnSrc = `(${itemVar}${node.indexVariable ? `, ${node.indexVariable}` : ''}) => ${keyExpr}`;
2200
2321
  const reconciler = ctx.n();
2201
2322
  const initList = ctx.n();
2323
+ const breakReset = breakVar ? `${breakVar} = false; ` : '';
2202
2324
  ctx.push(`let ${reconciler} = () => {};`);
2203
2325
  if (hydKeyed) {
2204
2326
  // claim-by-key hydration: `reconcileHydrated` attaches the region anchors
2205
2327
  // inside `parent` (pre-attach, `anchor.parentNode` is null) and peeks all
2206
2328
  // keys before claim-by-key consumes the walker, so server-rendered items
2207
2329
  // are adopted and wired in place instead of being rebuilt.
2208
- ctx.push(`const ${initList} = () => { ${reconciler} = reconcileHydrated(${anchor}, ${endAnchor}, ${arrExpr}, ${keyFnSrc}, (${itemVar}, __i, __e, __root) => ${renderItem}(${itemVar}${indexParam ? ', __i, __e' : ', __e'}, null, __root), __hydrate, ${parent}, ${skipK}); };`);
2330
+ ctx.push(`const ${initList} = () => { ${breakReset}${reconciler} = reconcileHydrated(${anchor}, ${endAnchor}, ${arrExpr}, ${keyFnSrc}, (${itemVar}, __i, __e, __root) => ${renderItem}(${itemVar}${indexParam ? ', __i, __e' : ', __e'}, null, __root), __hydrate, ${parent}, ${skipK}); };`);
2209
2331
  }
2210
2332
  else {
2211
- ctx.push(`const ${initList} = () => { ${reconciler} = reconcile(${anchor}, ${endAnchor}, ${arrExpr}, ${keyFnSrc}, (${itemVar}, __i, __e) => ${renderItem}(${itemVar}${indexParam ? ', __i, __e' : ', __e'})); };`);
2333
+ ctx.push(`const ${initList} = () => { ${breakReset}${reconciler} = reconcile(${anchor}, ${endAnchor}, ${arrExpr}, ${keyFnSrc}, (${itemVar}, __i, __e) => ${renderItem}(${itemVar}${indexParam ? ', __i, __e' : ', __e'})); };`);
2212
2334
  }
2213
2335
  if (emptyRenderName) {
2214
2336
  const isEmptyVar = ctx.n();
@@ -2220,7 +2342,7 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
2220
2342
  const __new = ${hasItems}();
2221
2343
  if (__first) { __first = false; __new; return; }
2222
2344
  if (__new !== ${isEmptyVar}) {
2223
- if (__new) ${reconciler}(${arrExpr});
2345
+ if (__new) {${breakVar ? ` ${breakVar} = false;` : ''} ${reconciler}(${arrExpr}); }
2224
2346
  return;
2225
2347
  }
2226
2348
  ${isEmptyVar} = !__new;
@@ -2236,24 +2358,30 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
2236
2358
  return null;
2237
2359
  pushEffect(`let __first = true;`, `effect(() => {
2238
2360
  const __nv = ${arrExpr};
2239
- if (__first) { __first = false; __nv; ${reconciler}(${arrExpr}); return; }
2240
- ${reconciler}(${arrExpr});
2361
+ if (__first) { __first = false; __nv; ${breakReset}${reconciler}(${arrExpr}); return; }
2362
+ ${breakVar ? `if (${breakVar}) ${breakVar} = false;` : ''}${reconciler}(${arrExpr});
2241
2363
  })`);
2242
2364
  }
2243
2365
  }
2244
2366
  else {
2245
2367
  const renderAllItems = (ind, collect) => {
2246
2368
  const lines = [];
2369
+ if (breakVar)
2370
+ lines.push(`${ind}${breakVar} = false;`);
2247
2371
  if (node.indexVariable) {
2248
2372
  lines.push(`${ind}let __i = 0;`);
2249
2373
  lines.push(`${ind}for (const ${itemVar} of ${arrExpr}) {`);
2250
2374
  lines.push(`${ind}\t${aw}${renderItem}(${itemVar}, __i, ${effectsVar}${collect ? `, null, ${collect}` : ''});`);
2251
2375
  lines.push(`${ind}\t__i++;`);
2376
+ if (breakVar)
2377
+ lines.push(`${ind}\tif (${breakVar}) break;`);
2252
2378
  lines.push(`${ind}}`);
2253
2379
  }
2254
2380
  else {
2255
2381
  lines.push(`${ind}for (const ${itemVar} of ${arrExpr}) {`);
2256
2382
  lines.push(`${ind}\t${aw}${renderItem}(${itemVar}, ${effectsVar}${collect ? `, null, ${collect}` : ''});`);
2383
+ if (breakVar)
2384
+ lines.push(`${ind}\tif (${breakVar}) break;`);
2257
2385
  lines.push(`${ind}}`);
2258
2386
  }
2259
2387
  return lines.join('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAsBP,MAAM,uBAAuB,CAAC;AA2T/B,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCnL;AAgmDD,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAqV9E"}
1
+ {"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAuBP,MAAM,uBAAuB,CAAC;AA2T/B,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCnL;AAytDD,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAqV9E"}
@@ -1,4 +1,4 @@
1
- import { IRRoot, ComponentIR, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, RuntimeStatement, ForLoop, TrackDecl, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, Expression, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
1
+ import { IRRoot, ComponentIR, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, RuntimeStatement, ForLoop, TrackDecl, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, BreakSignal, Expression, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
2
2
  import { VeskError, codeFrame } from '@vesk/compiler/src/errors';
3
3
  import { createBaseParser } from '@vesk/compiler/src/parser';
4
4
  import { skipWhitespace, findBalancedEnd, splitTopLevel, startsWithIdentifier, stripDeclKeyword, isWhitespaceChar, collapseNewlineWhitespace } from '@vesk/compiler/src/scan';
@@ -1410,6 +1410,13 @@ function processJSXCallbackBody(source, body) {
1410
1410
  nodes.push(...processJSXChildren(source, [c]));
1411
1411
  return nodes;
1412
1412
  }
1413
+ // A block-bodied callback — `.map((x) => { const y = …; return <jsx/>; })` —
1414
+ // is a statement-mode body: local declarations become runtime statements and
1415
+ // the terminal `return <jsx>` renders the item. Previously the block was
1416
+ // printed verbatim as an expression (`const y = …; return <li>`) and esbuild
1417
+ // rejected it with `Unexpected keyword 'const'`.
1418
+ if (body.type === 'BlockStatement')
1419
+ return processStatementModeBody(source, body.body);
1413
1420
  if (body.type === 'ParenthesizedExpression')
1414
1421
  return exprToIR(source, body.expression);
1415
1422
  return exprToIR(source, body);
@@ -1627,6 +1634,54 @@ function getReturnStatement(node) {
1627
1634
  }
1628
1635
  return null;
1629
1636
  }
1637
+ /**
1638
+ * True when `node`'s subtree contains a `continue`/`break` that targets the
1639
+ * loop `node` belongs to. Descent stops at nested loops (their control
1640
+ * statements bind to them, not to the enclosing loop) and at function
1641
+ * boundaries.
1642
+ */
1643
+ function containsLoopControl(node) {
1644
+ if (!node)
1645
+ return false;
1646
+ if (node.type === 'ContinueStatement' || node.type === 'BreakStatement')
1647
+ return true;
1648
+ if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' ||
1649
+ node.type === 'ArrowFunctionExpression')
1650
+ return false;
1651
+ if (node.type === 'ForStatement' || node.type === 'ForInStatement' ||
1652
+ node.type === 'ForOfStatement' || node.type === 'WhileStatement' ||
1653
+ node.type === 'DoWhileStatement')
1654
+ return false;
1655
+ if (node.type === 'BlockStatement')
1656
+ return node.body.some(containsLoopControl);
1657
+ if (node.type === 'IfStatement')
1658
+ return containsLoopControl(node.consequent) || containsLoopControl(node.alternate);
1659
+ if (node.type === 'SwitchStatement')
1660
+ return node.cases.some((c) => (c.consequent || []).some(containsLoopControl));
1661
+ if (node.type === 'TryStatement') {
1662
+ return containsLoopControl(node.block) || containsLoopControl(node.handler) || containsLoopControl(node.finalizer);
1663
+ }
1664
+ if (node.type === 'CatchClause')
1665
+ return containsLoopControl(node.body);
1666
+ if (node.type === 'LabeledStatement')
1667
+ return containsLoopControl(node.body);
1668
+ return false;
1669
+ }
1670
+ /**
1671
+ * Recognizes an `if (c) continue;` / `if (c) break;` guard (no `else`) and
1672
+ * returns the control node plus any statements that precede it inside the
1673
+ * branch block (`if (c) { foo(); continue; }`).
1674
+ */
1675
+ function getLoopControlGuard(consequent, kind) {
1676
+ const stmts = consequent.type === 'BlockStatement' ? consequent.body : [consequent];
1677
+ if (stmts.length === 0)
1678
+ return null;
1679
+ const want = kind === 'continue' ? 'ContinueStatement' : 'BreakStatement';
1680
+ const last = stmts[stmts.length - 1];
1681
+ if (!last || last.type !== want)
1682
+ return null;
1683
+ return { pre: stmts.slice(0, -1), node: last };
1684
+ }
1630
1685
  function isStatementMode(bodyStmts) {
1631
1686
  if (bodyStmts.some((s) => s.type === 'JSXElement' || s.type === 'JSXExpressionContainer' || s.type === 'JSXFragment'))
1632
1687
  return true;
@@ -1680,6 +1735,15 @@ function processIfStatement(source, stmt) {
1680
1735
  return [new OpaqueDynamicRegion(condExpr, consequent, alternate)];
1681
1736
  }
1682
1737
  function processForStatement(source, stmt, alternate = []) {
1738
+ // A loop with no JSX is pure computation: its value is the side effects it
1739
+ // performs on surrounding bindings. Leaving it as a reactive DOM region would
1740
+ // emit anchors and per-item render closures for no output — and a
1741
+ // `continue`/`break` inside it lands inside those closures as invalid JS
1742
+ // (`Unsyntactic continue`). Emit the loop verbatim instead so its control
1743
+ // flow runs in its original scope.
1744
+ if (stmt.body && !hasJSXInSubtree(stmt.body) && containsLoopControl(stmt.body)) {
1745
+ return [new RuntimeStatement(getSource(source, stmt), stmt, source)];
1746
+ }
1683
1747
  if (stmt.type === 'ForOfStatement') {
1684
1748
  const left = stmt.left;
1685
1749
  let itemVar = 'item';
@@ -1715,6 +1779,9 @@ function processForStatement(source, stmt, alternate = []) {
1715
1779
  return [];
1716
1780
  }
1717
1781
  function processWhileStatement(source, stmt) {
1782
+ if (stmt.body && !hasJSXInSubtree(stmt.body) && containsLoopControl(stmt.body)) {
1783
+ return [new RuntimeStatement(getSource(source, stmt), stmt, source)];
1784
+ }
1718
1785
  const condition = toExpression(source, stmt.test);
1719
1786
  const bodyTemplate = processBlockBody(source, stmt.body);
1720
1787
  const isDoWhile = stmt.type === 'DoWhileStatement';
@@ -1797,6 +1864,25 @@ function processStatementModeBody(source, bodyStmts, filename) {
1797
1864
  nodes.push(new OpaqueDynamicRegion(toExpression(source, stmt.test), consequent, alternate));
1798
1865
  break;
1799
1866
  }
1867
+ // `if (c) continue;` / `if (c) break;` — a loop-body guard. The loop body
1868
+ // is re-emitted as a per-item closure (map) or inline loop, so the control
1869
+ // statement cannot cross the branch closure. Rewrite the remainder of the
1870
+ // iteration into the guard's ELSE branch: `if (c) { pre } else { rest }`.
1871
+ // `continue` renders nothing in the consequent; `break` also sets the
1872
+ // region's break flag (a BreakSignal) so later iterations stop.
1873
+ if (!stmt.alternate) {
1874
+ const guardContinue = getLoopControlGuard(stmt.consequent, 'continue');
1875
+ const guardBreak = guardContinue ? null : getLoopControlGuard(stmt.consequent, 'break');
1876
+ const guard = guardContinue || guardBreak;
1877
+ if (guard) {
1878
+ const consequent = guard.pre.length ? processStatementModeBody(source, guard.pre, filename) : [];
1879
+ if (guardBreak)
1880
+ consequent.push(new BreakSignal());
1881
+ const alternate = processStatementModeBody(source, bodyStmts.slice(i + 1), filename);
1882
+ nodes.push(new OpaqueDynamicRegion(toExpression(source, stmt.test), consequent, alternate));
1883
+ break;
1884
+ }
1885
+ }
1800
1886
  nodes.push(...processIfStatement(source, stmt));
1801
1887
  }
1802
1888
  else if (stmt.type === 'ForOfStatement') {
@@ -1847,6 +1933,17 @@ function processStatementModeBody(source, bodyStmts, filename) {
1847
1933
  const { line, column } = offsetToLineCol(source, stmt.start ?? 0);
1848
1934
  throw VeskError.classDecl({ file: filename || '', line, column, code: codeFrame(source, line, column) });
1849
1935
  }
1936
+ else if (stmt.type === 'ContinueStatement') {
1937
+ // An unconditional `continue` at the top level of a loop body: everything
1938
+ // after it is dead code. Drop the remainder of the body.
1939
+ break;
1940
+ }
1941
+ else if (stmt.type === 'BreakStatement') {
1942
+ // An unconditional `break` at the top level of a loop body: stop the loop
1943
+ // and drop the remainder.
1944
+ nodes.push(new BreakSignal());
1945
+ break;
1946
+ }
1850
1947
  else {
1851
1948
  const raw = getSource(source, stmt);
1852
1949
  if (raw)
@@ -2038,6 +2135,13 @@ function warnStaleConstBindings(comp, file) {
2038
2135
  // pushed authors to inline helpers that were already correct.
2039
2136
  if (d.init.type === 'ArrowFunctionExpression' || d.init.type === 'FunctionExpression')
2040
2137
  continue;
2138
+ // `const x = derived(() => trackedValue)` is the DOCUMENTED fix this very
2139
+ // warning recommends, and it is live by construction. The recursion below
2140
+ // would still reach the tracked read inside the closure and flag it, so
2141
+ // a reactive factory call is excluded for the same reason a bare function
2142
+ // initializer is.
2143
+ if (isReactiveFactoryCall(d.init))
2144
+ continue;
2041
2145
  // A bare identifier initializer is an ALIAS, not a read: `const copy =
2042
2146
  // selCell` re-binds the cell and stays live. Only a read snapshots.
2043
2147
  if (d.init.type === 'Identifier' && reactive.has(d.init.name))
@@ -2094,6 +2198,21 @@ function warnStaleConstBindings(comp, file) {
2094
2198
  });
2095
2199
  }
2096
2200
  /** Every identifier name appearing anywhere in an expression (AST walk). */
2201
+ function isReactiveFactoryCall(node) {
2202
+ if (!node || node.type !== 'CallExpression')
2203
+ return false;
2204
+ const callee = node.callee;
2205
+ if (!callee)
2206
+ return false;
2207
+ // `derived(...)` is auto-imported, so the callee is a bare identifier; also
2208
+ // accept a namespace/dotted call (`$state.derived(...)`) defensively.
2209
+ if (callee.type === 'Identifier')
2210
+ return callee.name === 'derived';
2211
+ if (callee.type === 'MemberExpression' && !callee.computed) {
2212
+ return callee.property?.type === 'Identifier' && callee.property.name === 'derived';
2213
+ }
2214
+ return false;
2215
+ }
2097
2216
  function collectIdentifiers(node, into) {
2098
2217
  if (!node || typeof node !== 'object')
2099
2218
  return;
@@ -2104,6 +2223,21 @@ function collectIdentifiers(node, into) {
2104
2223
  }
2105
2224
  if (typeof node.type !== 'string')
2106
2225
  return;
2226
+ // A NON-computed member property (`learner.classId`) and a non-computed
2227
+ // object/class key (`{ classId: 1 }`) are names, not references. Collecting
2228
+ // them made `const klass = base.find(c => c.id === learner.classId)` look
2229
+ // like it read the tracked `classId` binding, when it only reads the loop
2230
+ // item's field — a false positive on correct per-iteration code.
2231
+ if (node.type === 'MemberExpression' && !node.computed) {
2232
+ collectIdentifiers(node.object, into);
2233
+ if (node.property?.type === 'MemberExpression')
2234
+ collectIdentifiers(node.property, into);
2235
+ return;
2236
+ }
2237
+ if ((node.type === 'Property' || node.type === 'PropertyDefinition' || node.type === 'MethodDefinition') && !node.computed) {
2238
+ collectIdentifiers(node.value, into);
2239
+ return;
2240
+ }
2107
2241
  if (node.type === 'Identifier' && typeof node.name === 'string')
2108
2242
  into.add(node.name);
2109
2243
  for (const key of Object.keys(node)) {
package/dist/ir.d.ts CHANGED
@@ -203,6 +203,21 @@ export declare class RuntimeStatement {
203
203
  source: string | null;
204
204
  constructor(raw: string, ast?: ESTreeNode | null, source?: string | null);
205
205
  }
206
+ /**
207
+ * A `break` targeting the enclosing reactive loop region.
208
+ *
209
+ * A statement-mode loop body is emitted as a per-item render closure (map) or
210
+ * an inline real loop (for/while). A `break` inside a nested `if` region is
211
+ * emitted inside a branch closure and cannot `break` the outer loop. The IR
212
+ * generator rewrites `if (c) break; rest` into `if (c) { <BreakSignal> } else
213
+ * { rest }`; codegen lowers this node to "set the region's break flag and stop
214
+ * emitting the current item" (map) or "set the flag; the loop checks it at the
215
+ * top of each pass" (inline loops). The server emits a native `break;` since
216
+ * its regions are inline.
217
+ */
218
+ export declare class BreakSignal {
219
+ constructor();
220
+ }
206
221
  export declare class ForLoop {
207
222
  init: string;
208
223
  condition: Expression;
@@ -223,5 +238,5 @@ export declare class HeadBlock {
223
238
  children: IRNode[];
224
239
  constructor(children: IRNode[]);
225
240
  }
226
- export type IRNode = StaticNode | TextNode | DynamicBinding | OpaqueDynamicRegion | MapRegion | WhileLoop | SwitchBlock | TryCatch | ForLoop | TrackDecl | RuntimeStatement | ComponentRef | ComponentCall | ServerBlock | ClientBlock | HeadBlock | SlotNode | PropSlot | PropSlotRender;
241
+ export type IRNode = StaticNode | TextNode | DynamicBinding | OpaqueDynamicRegion | MapRegion | WhileLoop | SwitchBlock | TryCatch | ForLoop | TrackDecl | RuntimeStatement | BreakSignal | ComponentRef | ComponentCall | ServerBlock | ClientBlock | HeadBlock | SlotNode | PropSlot | PropSlotRender;
227
242
  //# sourceMappingURL=ir.d.ts.map
package/dist/ir.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
package/dist/ir.js CHANGED
@@ -254,6 +254,21 @@ export class RuntimeStatement {
254
254
  this.source = source;
255
255
  }
256
256
  }
257
+ /**
258
+ * A `break` targeting the enclosing reactive loop region.
259
+ *
260
+ * A statement-mode loop body is emitted as a per-item render closure (map) or
261
+ * an inline real loop (for/while). A `break` inside a nested `if` region is
262
+ * emitted inside a branch closure and cannot `break` the outer loop. The IR
263
+ * generator rewrites `if (c) break; rest` into `if (c) { <BreakSignal> } else
264
+ * { rest }`; codegen lowers this node to "set the region's break flag and stop
265
+ * emitting the current item" (map) or "set the flag; the loop checks it at the
266
+ * top of each pass" (inline loops). The server emits a native `break;` since
267
+ * its regions are inline.
268
+ */
269
+ export class BreakSignal {
270
+ constructor() { }
271
+ }
257
272
  export class ForLoop {
258
273
  init;
259
274
  condition;
@@ -1 +1 @@
1
- {"version":3,"file":"server-jsgen.d.ts","sourceRoot":"","sources":["../src/server-jsgen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAOzE,OAAO,EAAkG,KAAK,WAAW,EAAE,MAAM,mCAAmC,CAAC;AA6DrK,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,GAAE,OAAe,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CA4EjJ;AAobD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAwD1F;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAuFD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAkCzE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAYhG"}
1
+ {"version":3,"file":"server-jsgen.d.ts","sourceRoot":"","sources":["../src/server-jsgen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAQzE,OAAO,EAAkG,KAAK,WAAW,EAAE,MAAM,mCAAmC,CAAC;AA6DrK,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,GAAE,OAAe,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CA+EjJ;AAqbD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAwD1F;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAuFD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAkCzE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAYhG"}
@@ -1,4 +1,4 @@
1
- import { Expression, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, ForLoop, TrackDecl, RuntimeStatement, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
1
+ import { Expression, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, ForLoop, TrackDecl, RuntimeStatement, ComponentRef, ComponentCall, BreakSignal, ServerBlock, ClientBlock, HeadBlock, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
2
2
  import { isStaticIR, collectTrackedNames, transformTracked, transformTrackedInit, semicolonizeStatement } from '@vesk/compiler/src/client-codegen';
3
3
  import { unwrapTrackCall, stripTrackGeneric, hasTopLevelComma, skipWhitespace, findBalancedEnd, startsWithIdentifier, callsIdentifier } from '@vesk/compiler/src/scan';
4
4
  import { escapeHtml, indent, exprJS, extractTopLevelNames, extractRuntimeNames, buildParamInit, VOID_ELEMENTS, __vskHydrate, __vskMarkerless, __vskImportedNames, setVskImportedNames, setVskForceClaim, takeVskForceClaim, nextVskId, } from '@vesk/compiler/src/server-utils';
@@ -125,6 +125,10 @@ export function irNodeToJS(node, importedNames, isAsync = false, tracked) {
125
125
  }
126
126
  return semicolonizeStatement(transformTracked(node, tracked || new Map()));
127
127
  }
128
+ // SSR regions are emitted inline inside a real loop, so a break signal is a
129
+ // native `break;` — it exits the loop the item body was emitted into.
130
+ if (node instanceof BreakSignal)
131
+ return `break;`;
128
132
  if (node instanceof SlotNode) {
129
133
  // Markerless mode drops the slot boundary comments: SSR output is plain
130
134
  // HTML and slot claims scope structurally (createLayoutSlot subject to the
@@ -343,15 +347,16 @@ function mapRegionToJS(node, isAsync = false, tracked) {
343
347
  }
344
348
  const loopArr = arrVar || arr;
345
349
  if (node.indexVariable) {
346
- lines.push('let __i = 0;');
350
+ const counter = `__i${nextVskId()}`;
351
+ lines.push(`let ${counter} = 0;`);
347
352
  lines.push(`for (const ${item} of ${loopArr}) {`);
348
- lines.push(indent(`const ${node.indexVariable} = __i;`));
353
+ lines.push(indent(`const ${node.indexVariable} = ${counter};`));
349
354
  for (const n of bodyForItem) {
350
355
  const code = irNodeToJS(n, null, isAsync, tracked);
351
356
  if (code)
352
357
  lines.push(indent(code));
353
358
  }
354
- lines.push(indent('__i++;'));
359
+ lines.push(indent(`${counter}++;`));
355
360
  lines.push(`}`);
356
361
  }
357
362
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/compiler",
3
- "version": "0.2.60",
3
+ "version": "0.2.61",
4
4
  "type": "module",
5
5
  "description": "Vesk compiler — lexer, parser, semantic analysis, IR, codegen",
6
6
  "main": "./dist/index.js",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@sveltejs/acorn-typescript": "^1.0.0",
23
- "@vesk/types": "^0.2.60",
23
+ "@vesk/types": "^0.2.61",
24
24
  "acorn": "^8.15.0",
25
25
  "esrap": "^2.3.0",
26
26
  "is-reference": "^3.0.0",