@vesk/vesk-cli 0.2.41 → 0.2.43

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.
Files changed (2) hide show
  1. package/dist/cli.js +1334 -523
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -184,6 +184,24 @@ var init_errors = __esm({
184
184
  tip: isBuiltin ? `"${name}" is a Vesk built-in. Use it directly \u2014 no manual import needed.` : ""
185
185
  });
186
186
  }
187
+ static vskNamespaceTag(context = {}) {
188
+ return new _VeskError(
189
+ "Namespace imports are not supported for `.vsk` modules.",
190
+ {
191
+ ...context,
192
+ code: context.code || "V0410",
193
+ suggestions: [
194
+ "Import the component by name: import { MyIcon } from './icons.vsk'",
195
+ "Rename on import: import { MyIcon as Icon } from './icons.vsk'"
196
+ ],
197
+ nextSteps: [
198
+ "A `.vsk` component is a registry entry keyed by its name, not a module namespace object, so `<ns.Icon />` cannot be resolved.",
199
+ "If you need a namespace object, import from a `.ts`/`.js` module instead \u2014 those are real ES modules."
200
+ ],
201
+ tip: "A `.vsk` module exposes its components as named exports; use a named or renamed import rather than `import * as ns`."
202
+ }
203
+ );
204
+ }
187
205
  static classDecl(context = {}) {
188
206
  return new _VeskError(
189
207
  "class declarations are not supported inside Vesk components.",
@@ -367,13 +385,30 @@ var init_ir = __esm({
367
385
  staticProps;
368
386
  loadFn;
369
387
  topLevelCode;
370
- constructor(components, imports = [], importedNames = /* @__PURE__ */ new Set(), staticProps = null, loadFn = null, topLevelCode = []) {
388
+ /**
389
+ * Same-file specifier exports (`export { A }`, `export { A as B }`) as
390
+ * `{ local, exported }` pairs. These are NOT emitted as JS: components live
391
+ * in the component registry rather than as top-level bindings, so a raw
392
+ * `export { A }` would reference an undefined identifier. The pairs become
393
+ * registry alias entries so the exported name is importable.
394
+ */
395
+ exportAliases;
396
+ /**
397
+ * Module specifiers re-exported from this file (`export * from './x.vsk'`,
398
+ * `export { A } from './x.vsk'`, `export * as ns from './x.vsk'`). The
399
+ * statements themselves are dropped — the target file is compiled and
400
+ * merged into this one's component registry instead.
401
+ */
402
+ reexportSources;
403
+ constructor(components, imports = [], importedNames = /* @__PURE__ */ new Set(), staticProps = null, loadFn = null, topLevelCode = [], exportAliases = [], reexportSources = []) {
371
404
  this.components = components;
372
405
  this.imports = imports;
373
406
  this.importedNames = importedNames;
374
407
  this.staticProps = staticProps;
375
408
  this.loadFn = loadFn;
376
409
  this.topLevelCode = topLevelCode;
410
+ this.exportAliases = exportAliases;
411
+ this.reexportSources = reexportSources;
377
412
  }
378
413
  };
379
414
  ComponentIR = class {
@@ -2283,6 +2318,16 @@ function runInHydrateBlock(fn) {
2283
2318
  throw error;
2284
2319
  }
2285
2320
  }
2321
+ function recordClaim(root3, record) {
2322
+ claimRegistry.set(record.el, record);
2323
+ if (!root3) return;
2324
+ const records = walkerClaimRecords.get(root3);
2325
+ if (records) records.push(record);
2326
+ else walkerClaimRecords.set(root3, [record]);
2327
+ }
2328
+ function isAdopted(el) {
2329
+ return claimRegistry.get(el)?.state === "adopted";
2330
+ }
2286
2331
  function reportHydrationIssue(issue) {
2287
2332
  if (!__mismatchHandler) return;
2288
2333
  try {
@@ -2304,13 +2349,15 @@ function reportMiss(kind, detail, loud) {
2304
2349
  }
2305
2350
  if (loud) devWarn(`${kind}: ${detail}`);
2306
2351
  }
2307
- function stampClaimed(el) {
2308
- if (__hydrateDevMode) {
2309
- try {
2310
- el.setAttribute(CLAIMED_ATTR, "");
2311
- } catch {
2312
- }
2313
- }
2352
+ function recordAdopted(root3, el, expectedTag) {
2353
+ recordClaim(root3, {
2354
+ state: "adopted",
2355
+ el,
2356
+ owner: root3,
2357
+ expectedTag,
2358
+ actualTag: el.tagName.toLowerCase(),
2359
+ detached: false
2360
+ });
2314
2361
  }
2315
2362
  function stripDirectTextNodes(el) {
2316
2363
  let text = "";
@@ -2361,8 +2408,8 @@ function scanTwins(container) {
2361
2408
  let a = false;
2362
2409
  let b = false;
2363
2410
  try {
2364
- a = el.hasAttribute(CLAIMED_ATTR);
2365
- b = prev.hasAttribute(CLAIMED_ATTR);
2411
+ a = isAdopted(el);
2412
+ b = isAdopted(prev);
2366
2413
  } catch {
2367
2414
  continue;
2368
2415
  }
@@ -2405,6 +2452,30 @@ function auditHydration(container) {
2405
2452
  }
2406
2453
  if (!sample && container.outerHTML) sample = String(container.outerHTML).slice(0, 800);
2407
2454
  }
2455
+ const structuralRecords = [];
2456
+ const seenRecords = /* @__PURE__ */ new Set();
2457
+ const collectWalkerRecords = (el) => {
2458
+ const records = walkerClaimRecords.get(el);
2459
+ if (records) {
2460
+ for (const record of records) {
2461
+ if (!seenRecords.has(record)) {
2462
+ seenRecords.add(record);
2463
+ structuralRecords.push(record);
2464
+ }
2465
+ }
2466
+ }
2467
+ for (let i = 0; i < el.children.length; i++) collectWalkerRecords(el.children[i]);
2468
+ };
2469
+ collectWalkerRecords(container);
2470
+ const structuralGhosts = structuralRecords.filter((record) => record.state === "ghost");
2471
+ if (structuralGhosts.length > 0) {
2472
+ unclaimed += structuralGhosts.length;
2473
+ if (orphanNames.length < 5) {
2474
+ orphanNames.push(
2475
+ `${structuralGhosts.length} structural hydration ghost(s) (${structuralGhosts.slice(0, 3).map((record) => `<${record.actualTag}> expected <${record.expectedTag}>`).join(", ")})`
2476
+ );
2477
+ }
2478
+ }
2408
2479
  const twinRes = scanTwins(container);
2409
2480
  const issues = [];
2410
2481
  if (unclaimed > 0) {
@@ -2432,6 +2503,14 @@ function auditHydration(container) {
2432
2503
  } catch {
2433
2504
  }
2434
2505
  }
2506
+ for (const record of structuralGhosts) {
2507
+ try {
2508
+ if (record.detached || !record.owner || record.el.parentNode !== record.owner) continue;
2509
+ record.el.remove();
2510
+ record.detached = true;
2511
+ } catch {
2512
+ }
2513
+ }
2435
2514
  }
2436
2515
  if (__mismatchHandler) {
2437
2516
  for (const issue of issues) {
@@ -2462,7 +2541,7 @@ ${report.sample}`
2462
2541
  }
2463
2542
  function underClaimedAncestor(el, container) {
2464
2543
  for (let n = el; n && n !== container; n = n.parentElement) {
2465
- if (n.nodeType === 1 && n.hasAttribute(CLAIMED_ATTR)) return true;
2544
+ if (n.nodeType === 1 && isAdopted(n)) return true;
2466
2545
  }
2467
2546
  return false;
2468
2547
  }
@@ -2523,7 +2602,7 @@ function checkMarkerIdentity(marker, el) {
2523
2602
  }
2524
2603
  }
2525
2604
  }
2526
- function adoptElement(marker, tag) {
2605
+ function adoptElement(root3, marker, tag) {
2527
2606
  const el = marker.nextElementSibling;
2528
2607
  if (!el) {
2529
2608
  marker.remove();
@@ -2534,10 +2613,10 @@ function adoptElement(marker, tag) {
2534
2613
  marker.remove();
2535
2614
  stripDirectTextNodes(el);
2536
2615
  captureSsrElementChildren(el);
2537
- stampClaimed(el);
2616
+ recordAdopted(root3, el, tag || el.tagName.toLowerCase());
2538
2617
  return el;
2539
2618
  }
2540
- function adoptElementRaw(marker, tag) {
2619
+ function adoptElementRaw(root3, marker, tag) {
2541
2620
  const el = marker.nextElementSibling;
2542
2621
  if (!el) {
2543
2622
  marker.remove();
@@ -2547,7 +2626,7 @@ function adoptElementRaw(marker, tag) {
2547
2626
  checkMarkerIdentity(marker, el);
2548
2627
  marker.remove();
2549
2628
  captureSsrElementChildren(el);
2550
- stampClaimed(el);
2629
+ recordAdopted(root3, el, tag || el.tagName.toLowerCase());
2551
2630
  return el;
2552
2631
  }
2553
2632
  function createHydrateWalker(container, markerList) {
@@ -2752,14 +2831,15 @@ function hydrateOnInteraction(container, componentFn, props, options = {}) {
2752
2831
  }
2753
2832
  };
2754
2833
  }
2755
- var __hydrateDevMode, CLAIMED_ATTR, __hydrateStrict, __mismatchHandler, _SHOW_COMMENT, _FILTER_ACCEPT, _FILTER_SKIP, WalkerEngine, StructuralWalker;
2834
+ var __hydrateDevMode, claimRegistry, walkerClaimRecords, __hydrateStrict, __mismatchHandler, _SHOW_COMMENT, _FILTER_ACCEPT, _FILTER_SKIP, WalkerEngine, StructuralWalker;
2756
2835
  var init_hydrate = __esm({
2757
2836
  "../runtime/src/hydrate.ts"() {
2758
2837
  "use strict";
2759
2838
  init_ripple_runtime();
2760
2839
  init_ripple_blocks();
2761
2840
  __hydrateDevMode = true;
2762
- CLAIMED_ATTR = "data-vsk-claimed";
2841
+ claimRegistry = /* @__PURE__ */ new WeakMap();
2842
+ walkerClaimRecords = /* @__PURE__ */ new WeakMap();
2763
2843
  __hydrateStrict = false;
2764
2844
  __mismatchHandler = null;
2765
2845
  _SHOW_COMMENT = 128;
@@ -2844,7 +2924,7 @@ var init_hydrate = __esm({
2844
2924
  break;
2845
2925
  }
2846
2926
  this.idx++;
2847
- const adopted = adoptElement(tm.comment, tag);
2927
+ const adopted = adoptElement(this.root, tm.comment, tag);
2848
2928
  if (adopted === null) {
2849
2929
  tm.state = "claimed";
2850
2930
  break;
@@ -2896,7 +2976,7 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
2896
2976
  break;
2897
2977
  }
2898
2978
  this.idx++;
2899
- const adopted = adoptElementRaw(tm.comment, tag);
2979
+ const adopted = adoptElementRaw(this.root, tm.comment, tag);
2900
2980
  if (adopted === null) {
2901
2981
  tm.state = "claimed";
2902
2982
  break;
@@ -2986,7 +3066,7 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
2986
3066
  tm.comment.remove();
2987
3067
  stripDirectTextNodes(el);
2988
3068
  captureSsrElementChildren(el);
2989
- stampClaimed(el);
3069
+ recordAdopted(this.root, el, el.tagName.toLowerCase());
2990
3070
  return { el };
2991
3071
  }
2992
3072
  claimByKey(key, options) {
@@ -3160,12 +3240,37 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
3160
3240
  const el = this.els[target];
3161
3241
  if (tag && el.tagName.toLowerCase() !== tag) {
3162
3242
  this.idx = this.advancePastSkippable(target + 1);
3243
+ const ghost = {
3244
+ state: "ghost",
3245
+ el,
3246
+ owner: this.root,
3247
+ expectedTag: tag || "div",
3248
+ actualTag: el.tagName.toLowerCase(),
3249
+ detached: false
3250
+ };
3251
+ recordClaim(this.root, ghost);
3252
+ if (this.root && el.parentNode === this.root) {
3253
+ try {
3254
+ el.remove();
3255
+ ghost.detached = true;
3256
+ } catch {
3257
+ }
3258
+ }
3259
+ const fresh2 = document.createElement(tag || "div");
3260
+ recordClaim(this.root, {
3261
+ state: "fresh",
3262
+ el: fresh2,
3263
+ owner: this.root,
3264
+ expectedTag: tag || "div",
3265
+ actualTag: fresh2.tagName.toLowerCase(),
3266
+ detached: false
3267
+ });
3163
3268
  reportMiss(
3164
3269
  "tag-mismatch",
3165
- `descriptor wanted <${tag}> but the SSR slot holds <${el.tagName.toLowerCase()}>; consuming one slot and rendering fresh.`,
3270
+ `descriptor wanted <${tag}> but the SSR slot holds <${el.tagName.toLowerCase()}>; consumed one slot, detached the local ghost, and rendered fresh.`,
3166
3271
  false
3167
3272
  );
3168
- return document.createElement(tag || "div");
3273
+ return fresh2;
3169
3274
  }
3170
3275
  if (this.adopted.has(el)) {
3171
3276
  target = this.advancePastSkippable(target + 1);
@@ -3175,10 +3280,19 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
3175
3280
  this.adopted.add(el);
3176
3281
  if (!raw2) stripDirectTextNodes(el);
3177
3282
  captureSsrElementChildren(el);
3178
- stampClaimed(el);
3283
+ recordAdopted(this.root, el, tag || el.tagName.toLowerCase());
3179
3284
  return el;
3180
3285
  }
3181
3286
  this.idx = this.els.length;
3287
+ const fresh = document.createElement(tag || "div");
3288
+ recordClaim(this.root, {
3289
+ state: "fresh",
3290
+ el: fresh,
3291
+ owner: this.root,
3292
+ expectedTag: tag || "div",
3293
+ actualTag: fresh.tagName.toLowerCase(),
3294
+ detached: false
3295
+ });
3182
3296
  reportMiss(
3183
3297
  "exhausted",
3184
3298
  `hydration claim missed <${tag || "element"}>; the client rendered more or different content than SSR.`,
@@ -3187,7 +3301,7 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
3187
3301
  // nodes) — telemetry-only, mirroring the marker engine.
3188
3302
  false
3189
3303
  );
3190
- return document.createElement(tag || "div");
3304
+ return fresh;
3191
3305
  }
3192
3306
  nextElement(tag, skipK = 0) {
3193
3307
  return this.claimAt(tag, skipK, false);
@@ -3236,7 +3350,7 @@ ${String(this.root.outerHTML).slice(0, 800)}` : ""),
3236
3350
  this.adopted.add(el);
3237
3351
  stripDirectTextNodes(el);
3238
3352
  captureSsrElementChildren(el);
3239
- stampClaimed(el);
3353
+ recordAdopted(this.root, el, el.tagName.toLowerCase());
3240
3354
  return { el };
3241
3355
  }
3242
3356
  this.idx = this.els.length;
@@ -3361,10 +3475,10 @@ function flattenLayoutChain(tree, pathParts, result = []) {
3361
3475
  if (matched) {
3362
3476
  const consumeCount = node.isCatchAll ? pathParts.length : segCount;
3363
3477
  const remaining = pathParts.slice(consumeCount);
3364
- const isLeaf = remaining.length === 0 || remaining.every((p) => p === "");
3478
+ const isLeaf2 = remaining.length === 0 || remaining.every((p) => p === "");
3365
3479
  if (node.standalone) result.length = 0;
3366
3480
  result.push(node);
3367
- if (isLeaf) {
3481
+ if (isLeaf2) {
3368
3482
  break;
3369
3483
  } else if ((node.children || []).length > 0) {
3370
3484
  flattenLayoutChain(node.children || [], remaining, result);
@@ -16774,9 +16888,9 @@ function looksLikeTypeAssertionAt(input, pos) {
16774
16888
  while (i < input.length && isIdentCharCode(input.charCodeAt(i))) i++;
16775
16889
  const name = input.slice(nameStart, i);
16776
16890
  if (HTML_TAGS.has(name) || VOID_ELEMENTS.has(name)) return false;
16777
- const isPrimitive = TS_PRIMITIVE_TYPES.has(name);
16891
+ const isPrimitive2 = TS_PRIMITIVE_TYPES.has(name);
16778
16892
  const isCapitalized = name[0] >= "A" && name[0] <= "Z";
16779
- if (!isPrimitive && !isCapitalized) return false;
16893
+ if (!isPrimitive2 && !isCapitalized) return false;
16780
16894
  if (input.charCodeAt(i) === 60) {
16781
16895
  let depth = 0;
16782
16896
  let j = i;
@@ -16825,6 +16939,15 @@ function matchKeywordSequence(input, words) {
16825
16939
  const c = input.charCodeAt(p);
16826
16940
  return isWsChar(c) || c === 123;
16827
16941
  }
16942
+ function withStandaloneTokens(fn) {
16943
+ const prev = standaloneTokens;
16944
+ standaloneTokens = true;
16945
+ try {
16946
+ return fn();
16947
+ } finally {
16948
+ standaloneTokens = prev;
16949
+ }
16950
+ }
16828
16951
  function VeskParserPlugin(config = {}) {
16829
16952
  return (Parser3) => {
16830
16953
  const tt = Parser3.tokTypes || types$1;
@@ -16840,6 +16963,10 @@ function VeskParserPlugin(config = {}) {
16840
16963
  constructor(options, input) {
16841
16964
  super(options, input);
16842
16965
  }
16966
+ /** True when JSX tags are recognised without parser-driven componentDepth. */
16967
+ #jsxAllowed() {
16968
+ return this.#componentDepth > 0 || standaloneTokens;
16969
+ }
16843
16970
  #isBlockContext() {
16844
16971
  const ctx2 = this.curContext();
16845
16972
  return ctx2 && (ctx2.token === "{" || ctx2.token === "function");
@@ -17069,7 +17196,7 @@ function VeskParserPlugin(config = {}) {
17069
17196
  }
17070
17197
  return super.readToken(this.input.codePointAt(this.pos));
17071
17198
  }
17072
- if (this.#componentDepth > 0 && code === 60 && this.#isBlockContext()) {
17199
+ if (this.#jsxAllowed() && code === 60 && this.#isBlockContext()) {
17073
17200
  const next = this.input.charCodeAt(this.pos + 1);
17074
17201
  const startsNewStatement = this.hasPrecedingLineBreak();
17075
17202
  const inType = this.inType;
@@ -17520,7 +17647,7 @@ function VeskParserPlugin(config = {}) {
17520
17647
  return VeskParser;
17521
17648
  };
17522
17649
  }
17523
- var VOID_ELEMENTS, TS_PRIMITIVE_TYPES, HTML_TAGS;
17650
+ var VOID_ELEMENTS, TS_PRIMITIVE_TYPES, HTML_TAGS, standaloneTokens;
17524
17651
  var init_vesk_plugin = __esm({
17525
17652
  "../compiler/src/vesk-plugin.ts"() {
17526
17653
  "use strict";
@@ -17543,6 +17670,7 @@ var init_vesk_plugin = __esm({
17543
17670
  ]);
17544
17671
  TS_PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["number", "string", "boolean", "any", "unknown", "never", "void", "object", "symbol", "bigint", "undefined", "null"]);
17545
17672
  HTML_TAGS = /* @__PURE__ */ new Set(["a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr"]);
17673
+ standaloneTokens = false;
17546
17674
  }
17547
17675
  });
17548
17676
 
@@ -17914,6 +18042,340 @@ var init_scan = __esm({
17914
18042
  }
17915
18043
  });
17916
18044
 
18045
+ // ../compiler/src/tokens.ts
18046
+ function tokenizeCode(code) {
18047
+ return withStandaloneTokens(() => {
18048
+ try {
18049
+ const ParserClass = createBaseParser();
18050
+ const tok = ParserClass.tokenizer(code, {
18051
+ ecmaVersion: "latest",
18052
+ sourceType: "module"
18053
+ });
18054
+ const out = [];
18055
+ let t;
18056
+ while ((t = tok.getToken()) && t.type && t.type.label !== "eof") {
18057
+ out.push({
18058
+ label: t.type.label,
18059
+ value: typeof t.value === "string" ? t.value : "",
18060
+ start: t.start,
18061
+ end: t.end
18062
+ });
18063
+ }
18064
+ return out;
18065
+ } catch {
18066
+ return null;
18067
+ }
18068
+ });
18069
+ }
18070
+ function containsIdentifier(code, name) {
18071
+ const tokens = tokenizeCode(code);
18072
+ if (tokens !== null) {
18073
+ for (const t of tokens) {
18074
+ if ((t.label === "name" || t.label === "jsxName") && t.value === name) return true;
18075
+ }
18076
+ return false;
18077
+ }
18078
+ return manualContainsIdentifier(code, name);
18079
+ }
18080
+ function isIdentifierImported(code, name) {
18081
+ const tokens = tokenizeCode(code);
18082
+ if (tokens !== null) {
18083
+ for (let i = 0; i < tokens.length; i++) {
18084
+ if (tokens[i].label !== "import") continue;
18085
+ let j = i + 1;
18086
+ while (j < tokens.length && tokens[j].label !== ";" && !(tokens[j].label === "name" && tokens[j].value === "from")) {
18087
+ j++;
18088
+ }
18089
+ for (let k = i + 1; k < j; k++) {
18090
+ if ((tokens[k].label === "name" || tokens[k].label === "jsxName") && tokens[k].value === name) return true;
18091
+ }
18092
+ i = j;
18093
+ }
18094
+ return false;
18095
+ }
18096
+ return manualIsIdentifierImported(code, name);
18097
+ }
18098
+ function extractImportNames(importText) {
18099
+ const tokens = tokenizeCode(importText);
18100
+ if (tokens !== null) {
18101
+ const names = [];
18102
+ let i = 0;
18103
+ while (i < tokens.length && tokens[i].label !== "import") i++;
18104
+ if (i >= tokens.length) return names;
18105
+ i++;
18106
+ if (i < tokens.length && tokens[i].label === "name" && tokens[i].value === "type") i++;
18107
+ if (i < tokens.length && tokens[i].label === "{") {
18108
+ i++;
18109
+ while (i < tokens.length && tokens[i].label !== "}") {
18110
+ const t = tokens[i];
18111
+ if (t.label === "name") {
18112
+ if (t.value === "type" || t.value === "typeof") {
18113
+ i++;
18114
+ continue;
18115
+ }
18116
+ let name = t.value;
18117
+ if (i + 2 < tokens.length && tokens[i + 1].label === "name" && tokens[i + 1].value === "as" && tokens[i + 2].label === "name") {
18118
+ name = tokens[i + 2].value;
18119
+ i += 2;
18120
+ }
18121
+ names.push(name);
18122
+ }
18123
+ i++;
18124
+ }
18125
+ return names;
18126
+ }
18127
+ if (i < tokens.length && tokens[i].label === "*") {
18128
+ while (i < tokens.length && tokens[i].label !== "name") i++;
18129
+ if (i < tokens.length) names.push(tokens[i].value);
18130
+ } else if (i < tokens.length && tokens[i].label === "name") {
18131
+ names.push(tokens[i].value);
18132
+ }
18133
+ return names;
18134
+ }
18135
+ return manualExtractImportNames(importText);
18136
+ }
18137
+ function importModuleTarget(importText) {
18138
+ const tokens = tokenizeCode(importText);
18139
+ if (tokens === null) return null;
18140
+ for (let i = tokens.length - 1; i >= 0; i--) {
18141
+ if (tokens[i].label === "string") return tokens[i].value;
18142
+ }
18143
+ return null;
18144
+ }
18145
+ function manualContainsIdentifier(code, name) {
18146
+ let i = 0;
18147
+ while (i < code.length) {
18148
+ const c = code[i];
18149
+ if (c === '"' || c === "'" || c === "`") {
18150
+ i = skipString(code, i);
18151
+ continue;
18152
+ }
18153
+ if (c === "/" && (code[i + 1] === "/" || code[i + 1] === "*")) {
18154
+ i = skipComment(code, i);
18155
+ continue;
18156
+ }
18157
+ if (isIdentStart(c) && code.slice(i, i + name.length) === name) {
18158
+ const after = i + name.length;
18159
+ if ((after >= code.length || !isIdentChar(code[after])) && (i === 0 || !isIdentChar(code[i - 1]))) return true;
18160
+ }
18161
+ i++;
18162
+ }
18163
+ return false;
18164
+ }
18165
+ function manualIsIdentifierImported(code, name) {
18166
+ let i = 0;
18167
+ while (i < code.length) {
18168
+ const c = code[i];
18169
+ if (c === '"' || c === "'" || c === "`") {
18170
+ i = skipString(code, i);
18171
+ continue;
18172
+ }
18173
+ if (c === "/" && (code[i + 1] === "/" || code[i + 1] === "*")) {
18174
+ i = skipComment(code, i);
18175
+ continue;
18176
+ }
18177
+ if (isIdentStart(c)) {
18178
+ let j = i + 1;
18179
+ while (j < code.length && isIdentChar(code[j])) j++;
18180
+ const word = code.slice(i, j);
18181
+ if (word === "import") {
18182
+ let k = j;
18183
+ while (k < code.length) {
18184
+ if (code[k] === ";" || code[k] === "\n") break;
18185
+ if (code[k] === '"' || code[k] === "'" || code[k] === "`") {
18186
+ k = skipString(code, k);
18187
+ continue;
18188
+ }
18189
+ if (isIdentStart(code[k]) && code.slice(k, k + name.length) === name) {
18190
+ const a = k + name.length;
18191
+ if ((a >= code.length || !isIdentChar(code[a])) && (k === 0 || !isIdentChar(code[k - 1]))) return true;
18192
+ }
18193
+ k++;
18194
+ }
18195
+ }
18196
+ i = j;
18197
+ continue;
18198
+ }
18199
+ i++;
18200
+ }
18201
+ return false;
18202
+ }
18203
+ function manualExtractImportNames(importText) {
18204
+ const names = [];
18205
+ const open = importText.indexOf("{");
18206
+ if (open !== -1) {
18207
+ const close = importText.indexOf("}", open + 1);
18208
+ if (close !== -1) {
18209
+ let i2 = open + 1;
18210
+ while (i2 < close) {
18211
+ const c = importText[i2];
18212
+ if (c === '"' || c === "'" || c === "`") {
18213
+ i2 = skipString(importText, i2);
18214
+ continue;
18215
+ }
18216
+ if (isIdentStart(c)) {
18217
+ let j = i2 + 1;
18218
+ while (j < close && isIdentChar(importText[j])) j++;
18219
+ let word = importText.slice(i2, j);
18220
+ if (word === "type" || word === "typeof") {
18221
+ i2 = j;
18222
+ continue;
18223
+ }
18224
+ let k = skipWhitespace(importText, j);
18225
+ if (importText.slice(k, k + 2) === "as" && !isIdentChar(importText[k + 2])) {
18226
+ let m = skipWhitespace(importText, k + 2);
18227
+ if (isIdentStart(importText[m])) {
18228
+ let n = m + 1;
18229
+ while (n < close && isIdentChar(importText[n])) n++;
18230
+ word = importText.slice(m, n);
18231
+ }
18232
+ }
18233
+ names.push(word);
18234
+ i2 = j;
18235
+ continue;
18236
+ }
18237
+ i2++;
18238
+ }
18239
+ return names;
18240
+ }
18241
+ }
18242
+ let i = 0;
18243
+ while (i < importText.length && !isIdentStart(importText[i])) i++;
18244
+ while (i < importText.length && isIdentChar(importText[i])) i++;
18245
+ i = skipWhitespace(importText, i);
18246
+ if (importText[i] === "*") {
18247
+ i = skipWhitespace(importText, i + 1);
18248
+ if (importText.slice(i, i + 2) === "as") i = skipWhitespace(importText, i + 2);
18249
+ if (isIdentStart(importText[i])) {
18250
+ let j = i + 1;
18251
+ while (j < importText.length && isIdentChar(importText[j])) j++;
18252
+ names.push(importText.slice(i, j));
18253
+ }
18254
+ } else if (isIdentStart(importText[i])) {
18255
+ let j = i + 1;
18256
+ while (j < importText.length && isIdentChar(importText[j])) j++;
18257
+ names.push(importText.slice(i, j));
18258
+ }
18259
+ return names;
18260
+ }
18261
+ function hasTopLevelValueDeclaration(code, name) {
18262
+ const tokens = tokenizeCode(code);
18263
+ if (tokens === null) return false;
18264
+ const declWords = ["const", "let", "var", "function", "class"];
18265
+ for (let i = 1; i < tokens.length; i++) {
18266
+ if (tokens[i].label !== "name" || tokens[i].value !== name) continue;
18267
+ const prev = tokens[i - 1];
18268
+ if (!prev || !declWords.includes(prev.value)) continue;
18269
+ if (i >= 2) {
18270
+ const pp2 = tokens[i - 2];
18271
+ if (pp2 && pp2.label === "name" && pp2.value === "export") continue;
18272
+ }
18273
+ return true;
18274
+ }
18275
+ return false;
18276
+ }
18277
+ function findSpecifierExports(code) {
18278
+ const tokens = tokenizeCode(code);
18279
+ if (tokens === null) return [];
18280
+ const out = [];
18281
+ for (let i = 0; i < tokens.length; i++) {
18282
+ if (tokens[i].label !== "export") continue;
18283
+ if (!tokens[i + 1] || tokens[i + 1].label !== "{") continue;
18284
+ let k = i + 2;
18285
+ let depth = 1;
18286
+ for (; k < tokens.length; k++) {
18287
+ const lbl = tokens[k].label;
18288
+ if (lbl === "string") {
18289
+ continue;
18290
+ }
18291
+ if (lbl === "{") depth++;
18292
+ else if (lbl === "}") {
18293
+ depth--;
18294
+ if (depth === 0) break;
18295
+ }
18296
+ }
18297
+ let isReexport = false;
18298
+ for (let j = k + 1; j < tokens.length; j++) {
18299
+ const lbl = tokens[j].label;
18300
+ if (lbl === "string") {
18301
+ isReexport = true;
18302
+ break;
18303
+ }
18304
+ if (lbl === ";" || lbl === "export" || lbl === "import" || lbl === "}") break;
18305
+ }
18306
+ if (depth !== 0 || isReexport) continue;
18307
+ const pairs = readSpecifierPairs(code, tokens[i + 1].end, tokens[k].end);
18308
+ if (pairs === null) continue;
18309
+ const stmtEnd = tokens[k].end;
18310
+ for (const [local, exported] of pairs) out.push({ local, exported, start: tokens[i].start, end: stmtEnd });
18311
+ i = k;
18312
+ }
18313
+ return out;
18314
+ }
18315
+ function readSpecifierPairs(code, from, to) {
18316
+ const tokens = tokenizeCode(`(${code.slice(from, to)})`);
18317
+ if (tokens === null || tokens.length < 2) return null;
18318
+ const pairs = [];
18319
+ let i = 1;
18320
+ while (i < tokens.length) {
18321
+ const local = tokens[i];
18322
+ if (!local || local.label === ")" || local.label === ";") break;
18323
+ if (local.label !== "name") return null;
18324
+ const asTok = tokens[i + 1];
18325
+ if (asTok && asTok.label === "name" && asTok.value === "as") {
18326
+ const exported = tokens[i + 2];
18327
+ if (!exported || exported.label !== "name") return null;
18328
+ pairs.push([local.value, exported.value]);
18329
+ i += 3;
18330
+ } else {
18331
+ pairs.push([local.value, local.value]);
18332
+ i += 1;
18333
+ }
18334
+ const sep8 = tokens[i];
18335
+ if (!sep8 || sep8.label !== ",") break;
18336
+ i += 1;
18337
+ }
18338
+ return pairs.length > 0 ? pairs : null;
18339
+ }
18340
+ function collectTrackDeclMarkers(node, out) {
18341
+ if (!node || typeof node !== "object") return;
18342
+ if (Array.isArray(node)) {
18343
+ for (const child of node) collectTrackDeclMarkers(child, out);
18344
+ return;
18345
+ }
18346
+ if (node.type === "ArrayPattern" && node.lazy === true && typeof node.start === "number") {
18347
+ out.add(node.start - 1);
18348
+ return;
18349
+ }
18350
+ for (const key of Object.keys(node)) {
18351
+ const value = node[key];
18352
+ if (value && typeof value === "object") collectTrackDeclMarkers(value, out);
18353
+ }
18354
+ }
18355
+ function stripTrackDeclMarkers(text, base, node) {
18356
+ const offsets = /* @__PURE__ */ new Set();
18357
+ collectTrackDeclMarkers(node, offsets);
18358
+ if (offsets.size === 0) return text;
18359
+ const sorted = [...offsets].sort((a, b) => a - b);
18360
+ let out = "";
18361
+ let prev = 0;
18362
+ for (const offset2 of sorted) {
18363
+ const i = offset2 - base;
18364
+ if (i < prev || i >= text.length) continue;
18365
+ out += text.slice(prev, i) + " ";
18366
+ prev = i + 1;
18367
+ }
18368
+ return out + text.slice(prev);
18369
+ }
18370
+ var init_tokens = __esm({
18371
+ "../compiler/src/tokens.ts"() {
18372
+ "use strict";
18373
+ init_parser();
18374
+ init_vesk_plugin();
18375
+ init_scan();
18376
+ }
18377
+ });
18378
+
17917
18379
  // ../compiler/src/parser.ts
17918
18380
  function isIdentChar2(code) {
17919
18381
  return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 95 || code === 36;
@@ -18134,8 +18596,19 @@ function createBaseParser() {
18134
18596
  function parse4(source, options = {}) {
18135
18597
  const ParserClass = createBaseParser();
18136
18598
  const { code, annotations } = preprocessForClauses(blankComments(source));
18599
+ const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
18600
+ const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
18601
+ let parseable = code;
18602
+ if (specifierExports.length > 0) {
18603
+ const edits = specifierExports.map((e) => code.slice(e.start, e.end)).map((text) => text.split("").map((ch) => ch === "\n" ? "\n" : " ").join(""));
18604
+ let cut = 0;
18605
+ for (const spec of specifierExports) {
18606
+ const blanked = edits[cut++];
18607
+ parseable = parseable.slice(0, spec.start) + blanked + parseable.slice(spec.end);
18608
+ }
18609
+ }
18137
18610
  try {
18138
- const ast = ParserClass.parse(code, {
18611
+ const ast = ParserClass.parse(parseable, {
18139
18612
  ecmaVersion: "latest",
18140
18613
  sourceType: "module",
18141
18614
  locations: true,
@@ -18145,6 +18618,11 @@ function parse4(source, options = {}) {
18145
18618
  if (annotations.length > 0) {
18146
18619
  ast.__vskAnnotations = annotations;
18147
18620
  }
18621
+ if (specifierExports.length > 0) {
18622
+ ast.__vskSpecifierExports = specifierExports.map(
18623
+ (e) => ({ local: e.local, exported: e.exported })
18624
+ );
18625
+ }
18148
18626
  return ast;
18149
18627
  } catch (e) {
18150
18628
  const err = e;
@@ -18185,6 +18663,7 @@ var init_parser = __esm({
18185
18663
  init_vesk_plugin();
18186
18664
  init_scan();
18187
18665
  init_errors();
18666
+ init_tokens();
18188
18667
  }
18189
18668
  });
18190
18669
 
@@ -18379,228 +18858,6 @@ var init_strip_ts = __esm({
18379
18858
  }
18380
18859
  });
18381
18860
 
18382
- // ../compiler/src/tokens.ts
18383
- function tokenizeCode(code) {
18384
- try {
18385
- const ParserClass = createBaseParser();
18386
- const tok = ParserClass.tokenizer(code, {
18387
- ecmaVersion: "latest",
18388
- sourceType: "module"
18389
- });
18390
- const out = [];
18391
- let t;
18392
- while ((t = tok.getToken()) && t.type && t.type.label !== "eof") {
18393
- out.push({
18394
- label: t.type.label,
18395
- value: typeof t.value === "string" ? t.value : "",
18396
- start: t.start,
18397
- end: t.end
18398
- });
18399
- }
18400
- return out;
18401
- } catch {
18402
- return null;
18403
- }
18404
- }
18405
- function containsIdentifier(code, name) {
18406
- const tokens = tokenizeCode(code);
18407
- if (tokens !== null) {
18408
- for (const t of tokens) {
18409
- if ((t.label === "name" || t.label === "jsxName") && t.value === name) return true;
18410
- }
18411
- return false;
18412
- }
18413
- return manualContainsIdentifier(code, name);
18414
- }
18415
- function isIdentifierImported(code, name) {
18416
- const tokens = tokenizeCode(code);
18417
- if (tokens !== null) {
18418
- for (let i = 0; i < tokens.length; i++) {
18419
- if (tokens[i].label !== "import") continue;
18420
- let j = i + 1;
18421
- while (j < tokens.length && tokens[j].label !== ";" && !(tokens[j].label === "name" && tokens[j].value === "from")) {
18422
- j++;
18423
- }
18424
- for (let k = i + 1; k < j; k++) {
18425
- if ((tokens[k].label === "name" || tokens[k].label === "jsxName") && tokens[k].value === name) return true;
18426
- }
18427
- i = j;
18428
- }
18429
- return false;
18430
- }
18431
- return manualIsIdentifierImported(code, name);
18432
- }
18433
- function extractImportNames(importText) {
18434
- const tokens = tokenizeCode(importText);
18435
- if (tokens !== null) {
18436
- const names = [];
18437
- let i = 0;
18438
- while (i < tokens.length && tokens[i].label !== "import") i++;
18439
- if (i >= tokens.length) return names;
18440
- i++;
18441
- if (i < tokens.length && tokens[i].label === "name" && tokens[i].value === "type") i++;
18442
- if (i < tokens.length && tokens[i].label === "{") {
18443
- i++;
18444
- while (i < tokens.length && tokens[i].label !== "}") {
18445
- const t = tokens[i];
18446
- if (t.label === "name") {
18447
- if (t.value === "type" || t.value === "typeof") {
18448
- i++;
18449
- continue;
18450
- }
18451
- let name = t.value;
18452
- if (i + 2 < tokens.length && tokens[i + 1].label === "name" && tokens[i + 1].value === "as" && tokens[i + 2].label === "name") {
18453
- name = tokens[i + 2].value;
18454
- i += 2;
18455
- }
18456
- names.push(name);
18457
- }
18458
- i++;
18459
- }
18460
- return names;
18461
- }
18462
- if (i < tokens.length && tokens[i].label === "*") {
18463
- while (i < tokens.length && tokens[i].label !== "name") i++;
18464
- if (i < tokens.length) names.push(tokens[i].value);
18465
- } else if (i < tokens.length && tokens[i].label === "name") {
18466
- names.push(tokens[i].value);
18467
- }
18468
- return names;
18469
- }
18470
- return manualExtractImportNames(importText);
18471
- }
18472
- function importModuleTarget(importText) {
18473
- const tokens = tokenizeCode(importText);
18474
- if (tokens === null) return null;
18475
- for (let i = tokens.length - 1; i >= 0; i--) {
18476
- if (tokens[i].label === "string") return tokens[i].value;
18477
- }
18478
- return null;
18479
- }
18480
- function manualContainsIdentifier(code, name) {
18481
- let i = 0;
18482
- while (i < code.length) {
18483
- const c = code[i];
18484
- if (c === '"' || c === "'" || c === "`") {
18485
- i = skipString(code, i);
18486
- continue;
18487
- }
18488
- if (c === "/" && (code[i + 1] === "/" || code[i + 1] === "*")) {
18489
- i = skipComment(code, i);
18490
- continue;
18491
- }
18492
- if (isIdentStart(c) && code.slice(i, i + name.length) === name) {
18493
- const after = i + name.length;
18494
- if ((after >= code.length || !isIdentChar(code[after])) && (i === 0 || !isIdentChar(code[i - 1]))) return true;
18495
- }
18496
- i++;
18497
- }
18498
- return false;
18499
- }
18500
- function manualIsIdentifierImported(code, name) {
18501
- let i = 0;
18502
- while (i < code.length) {
18503
- const c = code[i];
18504
- if (c === '"' || c === "'" || c === "`") {
18505
- i = skipString(code, i);
18506
- continue;
18507
- }
18508
- if (c === "/" && (code[i + 1] === "/" || code[i + 1] === "*")) {
18509
- i = skipComment(code, i);
18510
- continue;
18511
- }
18512
- if (isIdentStart(c)) {
18513
- let j = i + 1;
18514
- while (j < code.length && isIdentChar(code[j])) j++;
18515
- const word = code.slice(i, j);
18516
- if (word === "import") {
18517
- let k = j;
18518
- while (k < code.length) {
18519
- if (code[k] === ";" || code[k] === "\n") break;
18520
- if (code[k] === '"' || code[k] === "'" || code[k] === "`") {
18521
- k = skipString(code, k);
18522
- continue;
18523
- }
18524
- if (isIdentStart(code[k]) && code.slice(k, k + name.length) === name) {
18525
- const a = k + name.length;
18526
- if ((a >= code.length || !isIdentChar(code[a])) && (k === 0 || !isIdentChar(code[k - 1]))) return true;
18527
- }
18528
- k++;
18529
- }
18530
- }
18531
- i = j;
18532
- continue;
18533
- }
18534
- i++;
18535
- }
18536
- return false;
18537
- }
18538
- function manualExtractImportNames(importText) {
18539
- const names = [];
18540
- const open = importText.indexOf("{");
18541
- if (open !== -1) {
18542
- const close = importText.indexOf("}", open + 1);
18543
- if (close !== -1) {
18544
- let i2 = open + 1;
18545
- while (i2 < close) {
18546
- const c = importText[i2];
18547
- if (c === '"' || c === "'" || c === "`") {
18548
- i2 = skipString(importText, i2);
18549
- continue;
18550
- }
18551
- if (isIdentStart(c)) {
18552
- let j = i2 + 1;
18553
- while (j < close && isIdentChar(importText[j])) j++;
18554
- let word = importText.slice(i2, j);
18555
- if (word === "type" || word === "typeof") {
18556
- i2 = j;
18557
- continue;
18558
- }
18559
- let k = skipWhitespace(importText, j);
18560
- if (importText.slice(k, k + 2) === "as" && !isIdentChar(importText[k + 2])) {
18561
- let m = skipWhitespace(importText, k + 2);
18562
- if (isIdentStart(importText[m])) {
18563
- let n = m + 1;
18564
- while (n < close && isIdentChar(importText[n])) n++;
18565
- word = importText.slice(m, n);
18566
- }
18567
- }
18568
- names.push(word);
18569
- i2 = j;
18570
- continue;
18571
- }
18572
- i2++;
18573
- }
18574
- return names;
18575
- }
18576
- }
18577
- let i = 0;
18578
- while (i < importText.length && !isIdentStart(importText[i])) i++;
18579
- while (i < importText.length && isIdentChar(importText[i])) i++;
18580
- i = skipWhitespace(importText, i);
18581
- if (importText[i] === "*") {
18582
- i = skipWhitespace(importText, i + 1);
18583
- if (importText.slice(i, i + 2) === "as") i = skipWhitespace(importText, i + 2);
18584
- if (isIdentStart(importText[i])) {
18585
- let j = i + 1;
18586
- while (j < importText.length && isIdentChar(importText[j])) j++;
18587
- names.push(importText.slice(i, j));
18588
- }
18589
- } else if (isIdentStart(importText[i])) {
18590
- let j = i + 1;
18591
- while (j < importText.length && isIdentChar(importText[j])) j++;
18592
- names.push(importText.slice(i, j));
18593
- }
18594
- return names;
18595
- }
18596
- var init_tokens = __esm({
18597
- "../compiler/src/tokens.ts"() {
18598
- "use strict";
18599
- init_parser();
18600
- init_scan();
18601
- }
18602
- });
18603
-
18604
18861
  // ../compiler/src/module-imports.ts
18605
18862
  import { readFileSync as readFileSync2, existsSync as existsSync2, realpathSync, statSync } from "node:fs";
18606
18863
  import { createRequire as createRequire2 } from "node:module";
@@ -19550,19 +19807,65 @@ function collectVskImportPaths(imports, sourcePath2) {
19550
19807
  if (stripTypeImport(imp) === null) continue;
19551
19808
  const target = vskImportTarget(imp);
19552
19809
  if (!target) continue;
19553
- if (target.startsWith(".")) {
19554
- const full = resolve2(dirname3(sourcePath2), target);
19555
- if (existsSync3(full)) out.push(full);
19556
- continue;
19557
- }
19558
- const aliased = resolveImportPath(target, dirname3(sourcePath2));
19559
- if (aliased !== target && existsSync3(aliased)) out.push(aliased);
19810
+ const full = resolveVskTarget(target, sourcePath2);
19811
+ if (full) out.push(full);
19560
19812
  }
19561
19813
  return out;
19562
19814
  }
19815
+ function collectVskReexportPaths(reexportSources, sourcePath2) {
19816
+ const out = [];
19817
+ for (const spec of reexportSources) {
19818
+ if (!spec.endsWith(".vsk")) continue;
19819
+ const full = resolveVskTarget(spec, sourcePath2);
19820
+ if (full) out.push(full);
19821
+ }
19822
+ return out;
19823
+ }
19824
+ function resolveVskTarget(target, sourcePath2) {
19825
+ if (target.startsWith(".")) {
19826
+ const full = resolve2(dirname3(sourcePath2), target);
19827
+ return existsSync3(full) ? full : null;
19828
+ }
19829
+ const aliased = resolveImportPath(target, dirname3(sourcePath2));
19830
+ return aliased !== target && existsSync3(aliased) ? aliased : null;
19831
+ }
19832
+ function vskImportValueNames(imports) {
19833
+ const names = [];
19834
+ for (const imp of imports) {
19835
+ if (stripTypeImport(imp) === null) continue;
19836
+ if (vskImportTarget(imp) === null) continue;
19837
+ for (const pair of importBindingPairs(imp)) {
19838
+ if (pair.imported === "default" || pair.imported === "*") continue;
19839
+ names.push(pair.local);
19840
+ }
19841
+ }
19842
+ return names;
19843
+ }
19563
19844
  function vskImportLines(source) {
19564
19845
  return extractImportStatements(source).filter((imp) => vskImportTarget(imp) !== null && stripTypeImport(imp) !== null);
19565
19846
  }
19847
+ function vskRegistryAliases(importLines, exportAliases) {
19848
+ const aliases = [];
19849
+ for (const alias of exportAliases) {
19850
+ if (alias.local !== alias.exported) aliases.push({ local: alias.local, exported: alias.exported });
19851
+ }
19852
+ for (const imp of importLines) {
19853
+ if (stripTypeImport(imp) === null) continue;
19854
+ if (vskImportTarget(imp) === null) continue;
19855
+ for (const pair of importBindingPairs(imp)) {
19856
+ if (pair.imported === "default" || pair.imported === "*") continue;
19857
+ if (pair.local !== pair.imported) aliases.push({ local: pair.imported, exported: pair.local });
19858
+ }
19859
+ }
19860
+ return aliases;
19861
+ }
19862
+ function applyVskRegistryAliases(componentMap, aliases) {
19863
+ for (const { local, exported } of aliases) {
19864
+ if (componentMap.has(exported)) continue;
19865
+ const fn = componentMap.get(local);
19866
+ if (fn) componentMap.set(exported, fn);
19867
+ }
19868
+ }
19566
19869
  function isTypeOnlyImport(stmt) {
19567
19870
  if (!stmt || stmt.type !== "ImportDeclaration") return false;
19568
19871
  if (stmt.importKind === "type") return true;
@@ -19873,6 +20176,22 @@ function getJSXTagName(nameNode) {
19873
20176
  }
19874
20177
  return "unknown";
19875
20178
  }
20179
+ function jsxTagRootName(nameNode) {
20180
+ let node = nameNode;
20181
+ while (node && node.type === "JSXMemberExpression") node = node.object;
20182
+ return node && node.type === "JSXIdentifier" ? node.name : "";
20183
+ }
20184
+ function collectVskNamespaceLocals(ast) {
20185
+ const out = /* @__PURE__ */ new Set();
20186
+ for (const node of ast.body || []) {
20187
+ if (node.type !== "ImportDeclaration") continue;
20188
+ if (typeof node.source?.value !== "string" || !node.source.value.endsWith(".vsk")) continue;
20189
+ for (const spec of node.specifiers || []) {
20190
+ if (spec.type === "ImportNamespaceSpecifier" && spec.local?.name) out.add(spec.local.name);
20191
+ }
20192
+ }
20193
+ return out;
20194
+ }
19876
20195
  function isHTMLTag(name) {
19877
20196
  return name.length > 0 && name[0] === name[0].toLowerCase();
19878
20197
  }
@@ -20241,6 +20560,11 @@ function processJSXElement(source, element) {
20241
20560
  return [new HeadBlock(children2)];
20242
20561
  }
20243
20562
  if (nameNode && nameNode.type === "JSXMemberExpression") {
20563
+ const root3 = jsxTagRootName(nameNode);
20564
+ if (currentVskNamespaceLocals && currentVskNamespaceLocals.has(root3)) {
20565
+ const { line, column } = offsetToLineCol2(source, nameNode.start ?? 0);
20566
+ throw VeskError.vskNamespaceTag({ file: currentSourceFile, line, column, code: codeFrame(source, line, column) });
20567
+ }
20244
20568
  const { props, spreadProps, slots } = extractProps(source, element);
20245
20569
  const children2 = selfClosing ? [] : processJSXChildren(source, element.children || []);
20246
20570
  return [new ComponentCall(tagName, props, [...children2, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start, getSource(source, nameNode))];
@@ -20656,217 +20980,263 @@ function generateIR(ast, source, filename) {
20656
20980
  let staticProps = null;
20657
20981
  let loadFn = null;
20658
20982
  const topLevelCode = [];
20659
- for (const node of ast.body) {
20660
- if (node.type === "ImportDeclaration") {
20661
- const raw2 = getSource(source, node);
20662
- let cleaned = stripTypeImport(raw2);
20663
- if (cleaned === null) continue;
20664
- cleaned = normalizeRuntimeSpecifier(cleaned);
20665
- imports.push(cleaned);
20666
- for (const spec of node.specifiers) {
20667
- if (spec.importKind === "type") continue;
20668
- if (spec.type === "ImportSpecifier") {
20669
- importedNames.add(spec.local.name);
20983
+ const exportAliases = [];
20984
+ const reexportSources = [];
20985
+ for (const pair of ast.__vskSpecifierExports || []) {
20986
+ exportAliases.push({ local: pair.local, exported: pair.exported });
20987
+ }
20988
+ const vskNamespaceLocals = collectVskNamespaceLocals(ast);
20989
+ const prevNamespaceLocals = currentVskNamespaceLocals;
20990
+ const prevSourceFile = currentSourceFile;
20991
+ currentVskNamespaceLocals = vskNamespaceLocals;
20992
+ currentSourceFile = file;
20993
+ try {
20994
+ for (const node of ast.body) {
20995
+ if (node.type === "ImportDeclaration") {
20996
+ const raw2 = getSource(source, node);
20997
+ let cleaned = stripTypeImport(raw2);
20998
+ if (cleaned === null) continue;
20999
+ cleaned = normalizeRuntimeSpecifier(cleaned);
21000
+ imports.push(cleaned);
21001
+ for (const spec of node.specifiers) {
21002
+ if (spec.importKind === "type") continue;
21003
+ if (spec.type === "ImportSpecifier") {
21004
+ importedNames.add(spec.local.name);
21005
+ }
20670
21006
  }
21007
+ continue;
20671
21008
  }
20672
- continue;
20673
- }
20674
- if (node.type === "ExportNamedDeclaration" && node.declaration && !staticProps) {
20675
- const decl = node.declaration;
20676
- const fnName = decl.type === "FunctionDeclaration" ? decl.id?.name : decl.type === "VariableDeclaration" ? decl.declarations[0]?.id?.name : null;
20677
- if (fnName === "getStaticProps") {
20678
- staticProps = stripCodeTypes(getSource(source, decl));
21009
+ if (node.type === "ExportNamedDeclaration" && node.declaration && !staticProps) {
21010
+ const decl = node.declaration;
21011
+ const fnName = decl.type === "FunctionDeclaration" ? decl.id?.name : decl.type === "VariableDeclaration" ? decl.declarations[0]?.id?.name : null;
21012
+ if (fnName === "getStaticProps") {
21013
+ staticProps = stripCodeTypes(getSource(source, decl));
21014
+ continue;
21015
+ }
21016
+ }
21017
+ if (node.type === "ExportNamedDeclaration" && node.declaration && !loadFn) {
21018
+ const decl = node.declaration;
21019
+ const fnName = decl.type === "FunctionDeclaration" ? decl.id?.name : decl.type === "VariableDeclaration" ? decl.declarations[0]?.id?.name : null;
21020
+ if (fnName === "load") {
21021
+ loadFn = stripCodeTypes(getSource(source, decl));
21022
+ continue;
21023
+ }
21024
+ }
21025
+ if (node.type === "ExportNamedDeclaration" && node.declaration) {
21026
+ const decl = node.declaration;
21027
+ if (decl.type === "VariableDeclaration") {
21028
+ const declName = decl.declarations[0]?.id?.name;
21029
+ if (declName === "standalone") {
21030
+ continue;
21031
+ }
21032
+ }
21033
+ }
21034
+ if (node.type === "ExportNamedDeclaration" && !node.declaration) {
21035
+ if (node.source) {
21036
+ if (typeof node.source.value === "string") reexportSources.push(node.source.value);
21037
+ for (const spec of node.specifiers || []) {
21038
+ if (spec.type === "ExportSpecifier") {
21039
+ const localName = spec.local && spec.local.name;
21040
+ const exportedName = spec.exported && spec.exported.name;
21041
+ if (typeof localName === "string" && typeof exportedName === "string") {
21042
+ exportAliases.push({ local: localName, exported: exportedName });
21043
+ }
21044
+ }
21045
+ }
21046
+ continue;
21047
+ }
21048
+ for (const spec of node.specifiers || []) {
21049
+ if (spec.type === "ExportSpecifier") {
21050
+ const localName = spec.local && spec.local.name;
21051
+ const exportedName = spec.exported && spec.exported.name;
21052
+ if (typeof localName === "string" && typeof exportedName === "string") {
21053
+ exportAliases.push({ local: localName, exported: exportedName });
21054
+ }
21055
+ }
21056
+ }
20679
21057
  continue;
20680
21058
  }
20681
- }
20682
- if (node.type === "ExportNamedDeclaration" && node.declaration && !loadFn) {
20683
- const decl = node.declaration;
20684
- const fnName = decl.type === "FunctionDeclaration" ? decl.id?.name : decl.type === "VariableDeclaration" ? decl.declarations[0]?.id?.name : null;
20685
- if (fnName === "load") {
20686
- loadFn = stripCodeTypes(getSource(source, decl));
21059
+ if (node.type === "ExportAllDeclaration") {
21060
+ if (node.source && typeof node.source.value === "string") reexportSources.push(node.source.value);
20687
21061
  continue;
20688
21062
  }
20689
- }
20690
- if (node.type === "ExportNamedDeclaration" && node.declaration) {
20691
- const decl = node.declaration;
20692
- if (decl.type === "VariableDeclaration") {
20693
- const declName = decl.declarations[0]?.id?.name;
20694
- if (declName === "standalone") {
20695
- continue;
21063
+ let inner = node;
21064
+ let exported = false;
21065
+ let defaultExport = false;
21066
+ if (node.type === "ExportNamedDeclaration" && node.declaration) {
21067
+ inner = node.declaration;
21068
+ exported = true;
21069
+ } else if (node.type === "ExportDefaultDeclaration" && node.declaration) {
21070
+ inner = node.declaration;
21071
+ exported = true;
21072
+ defaultExport = true;
21073
+ }
21074
+ if (inner.type === "ComponentDeclaration") {
21075
+ } else if (inner.type === "ClassDeclaration") {
21076
+ const { line, column } = offsetToLineCol2(source, inner.start ?? 0);
21077
+ throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
21078
+ } else if (inner.type === "TSEnumDeclaration") {
21079
+ const code = processEnum(inner, source, exported);
21080
+ topLevelCode.push(code);
21081
+ continue;
21082
+ } else {
21083
+ topLevelCode.push(getSource(source, node));
21084
+ continue;
21085
+ }
21086
+ const name = inner.id.name;
21087
+ const paramNames = getParamNames(inner.params, source);
21088
+ const firstParam = inner.params?.[0];
21089
+ const propsAlias = firstParam && firstParam.type === "Identifier" ? firstParam.name : null;
21090
+ const propsType = getPropsType(inner.params, source);
21091
+ const bodyStmts = inner.body.body;
21092
+ const isClientComp = !!inner.client;
21093
+ const prevSlotProps = __slotProps;
21094
+ __slotProps = slotPropNamesFromType(propsType);
21095
+ __propsParam = propsAlias || null;
21096
+ if (isStatementMode(bodyStmts)) {
21097
+ const raw2 = processStatementModeBody(source, bodyStmts, file);
21098
+ const { body, css } = extractStyle(raw2);
21099
+ validateBlocks(name, isClientComp, body, file, source);
21100
+ const comp = new ComponentIR(name, paramNames, body, { mode: "statement", exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
21101
+ comp.style = css;
21102
+ components.push(comp);
21103
+ __slotProps = prevSlotProps;
21104
+ } else {
21105
+ const guardClauses = [];
21106
+ let mainReturn = null;
21107
+ const preamble = [];
21108
+ for (const stmt of bodyStmts) {
21109
+ if (stmt.type === "VeskBlock") {
21110
+ const innerBody = processStatementModeBody(source, stmt.body, file);
21111
+ if (stmt.tag === "server") {
21112
+ preamble.push(new ServerBlock(innerBody));
21113
+ } else if (stmt.tag === "client") {
21114
+ preamble.push(new ClientBlock(innerBody));
21115
+ }
21116
+ } else if (stmt.type === "ReturnStatement") {
21117
+ mainReturn = stmt;
21118
+ } else if (isTrackDeclaration(stmt)) {
21119
+ const elements = stmt.declarations[0].id.elements;
21120
+ const trackName = elements[0]?.name;
21121
+ const rawName = elements.length > 1 ? elements[1]?.name : null;
21122
+ const init = getSource(source, stmt.declarations[0].init);
21123
+ if (trackName) preamble.push(new TrackDecl(trackName, init, rawName));
21124
+ const refName = getComponentRefName(stmt);
21125
+ if (refName) preamble.push(new ComponentRef(refName));
21126
+ } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
21127
+ guardClauses.push(stmt);
21128
+ } else if (stmt.type === "ClassDeclaration") {
21129
+ const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
21130
+ throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
21131
+ } else {
21132
+ const raw2 = getSource(source, stmt);
21133
+ if (raw2) preamble.push(new RuntimeStatement(raw2, stmt, source));
21134
+ }
20696
21135
  }
21136
+ const guardBody = buildGuardChain(source, guardClauses, mainReturn);
21137
+ const { body, css } = extractStyle([...preamble, ...guardBody]);
21138
+ validateBlocks(name, isClientComp, body, file, source);
21139
+ const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
21140
+ comp.style = css;
21141
+ components.push(comp);
21142
+ __slotProps = prevSlotProps;
20697
21143
  }
20698
21144
  }
20699
- let inner = node;
20700
- let exported = false;
20701
- let defaultExport = false;
20702
- if (node.type === "ExportNamedDeclaration" && node.declaration) {
20703
- inner = node.declaration;
20704
- exported = true;
20705
- } else if (node.type === "ExportDefaultDeclaration" && node.declaration) {
20706
- inner = node.declaration;
20707
- exported = true;
20708
- defaultExport = true;
20709
- }
20710
- if (inner.type === "ComponentDeclaration") {
20711
- } else if (inner.type === "ClassDeclaration") {
20712
- const { line, column } = offsetToLineCol2(source, inner.start ?? 0);
20713
- throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
20714
- } else if (inner.type === "TSEnumDeclaration") {
20715
- const code = processEnum(inner, source, exported);
20716
- topLevelCode.push(code);
20717
- continue;
20718
- } else {
20719
- topLevelCode.push(getSource(source, node));
20720
- continue;
20721
- }
20722
- const name = inner.id.name;
20723
- const paramNames = getParamNames(inner.params, source);
20724
- const firstParam = inner.params?.[0];
20725
- const propsAlias = firstParam && firstParam.type === "Identifier" ? firstParam.name : null;
20726
- const propsType = getPropsType(inner.params, source);
20727
- const bodyStmts = inner.body.body;
20728
- const isClientComp = !!inner.client;
20729
- const prevSlotProps = __slotProps;
20730
- __slotProps = slotPropNamesFromType(propsType);
20731
- __propsParam = propsAlias || null;
20732
- if (isStatementMode(bodyStmts)) {
20733
- const raw2 = processStatementModeBody(source, bodyStmts, file);
20734
- const { body, css } = extractStyle(raw2);
20735
- validateBlocks(name, isClientComp, body, file, source);
20736
- const comp = new ComponentIR(name, paramNames, body, { mode: "statement", exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
20737
- comp.style = css;
20738
- components.push(comp);
20739
- __slotProps = prevSlotProps;
20740
- } else {
20741
- const guardClauses = [];
20742
- let mainReturn = null;
20743
- const preamble = [];
20744
- for (const stmt of bodyStmts) {
20745
- if (stmt.type === "VeskBlock") {
20746
- const innerBody = processStatementModeBody(source, stmt.body, file);
20747
- if (stmt.tag === "server") {
20748
- preamble.push(new ServerBlock(innerBody));
20749
- } else if (stmt.tag === "client") {
20750
- preamble.push(new ClientBlock(innerBody));
20751
- }
20752
- } else if (stmt.type === "ReturnStatement") {
20753
- mainReturn = stmt;
20754
- } else if (isTrackDeclaration(stmt)) {
20755
- const elements = stmt.declarations[0].id.elements;
20756
- const trackName = elements[0]?.name;
20757
- const rawName = elements.length > 1 ? elements[1]?.name : null;
20758
- const init = getSource(source, stmt.declarations[0].init);
20759
- if (trackName) preamble.push(new TrackDecl(trackName, init, rawName));
20760
- const refName = getComponentRefName(stmt);
20761
- if (refName) preamble.push(new ComponentRef(refName));
20762
- } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
20763
- guardClauses.push(stmt);
20764
- } else if (stmt.type === "ClassDeclaration") {
20765
- const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
20766
- throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
20767
- } else {
20768
- const raw2 = getSource(source, stmt);
20769
- if (raw2) preamble.push(new RuntimeStatement(raw2, stmt, source));
20770
- }
20771
- }
20772
- const guardBody = buildGuardChain(source, guardClauses, mainReturn);
20773
- const { body, css } = extractStyle([...preamble, ...guardBody]);
20774
- validateBlocks(name, isClientComp, body, file, source);
20775
- const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
20776
- comp.style = css;
20777
- components.push(comp);
20778
- __slotProps = prevSlotProps;
20779
- }
20780
- }
20781
- const asyncNames = new Set(components.filter((c) => c.isAsync || c.ssrAwait).map((c) => c.name));
20782
- for (const comp of components) {
20783
- if (asyncNames.has(comp.name)) continue;
20784
- const called2 = /* @__PURE__ */ new Map();
20785
- collectComponentCalls(comp.body, called2);
20786
- for (const [childName, start] of called2) {
20787
- if (!asyncNames.has(childName)) continue;
20788
- const { line, column } = offsetToLineCol2(source, start >= 0 ? start : 0);
20789
- throw VeskError.asyncChildInSyncParent(comp.name, childName, { file, line, column, code: codeFrame(source, line, column) });
20790
- }
20791
- }
20792
- const autoImportable = [
20793
- "useFetch",
20794
- "useRouter",
20795
- "useParams",
20796
- "usePathname",
20797
- "useSearchParams",
20798
- "useNavigate",
20799
- "defineAction",
20800
- "Form",
20801
- "Field",
20802
- "required",
20803
- "email",
20804
- "minLength",
20805
- "maxLength",
20806
- "pattern",
20807
- "custom",
20808
- "Link",
20809
- "NavLink",
20810
- "Outlet",
20811
- "Redirect",
20812
- "Image",
20813
- "Portal",
20814
- "Experiment",
20815
- "LoadingIndicator",
20816
- "useLoadingIndicator",
20817
- "JsonLd",
20818
- "ArticleSchema",
20819
- "ProductSchema",
20820
- "FAQPageSchema",
20821
- "BreadcrumbListSchema",
20822
- "OrganizationSchema",
20823
- "LocalBusinessSchema",
20824
- "VideoSchema",
20825
- "effect",
20826
- "derived",
20827
- "untrack",
20828
- "peek",
20829
- "tick",
20830
- "flushSync",
20831
- "on_destroy",
20832
- "createContext",
20833
- "redirect",
20834
- "permanentRedirect",
20835
- "notFound",
20836
- "NotFoundError",
20837
- "createResource",
20838
- "getAction",
20839
- "validateActionInput",
20840
- "issuesToFieldMap",
20841
- "isFormAction",
20842
- "Show",
20843
- "For",
20844
- "Switch",
20845
- "Match"
20846
- ];
20847
- const called = collectCallAndJsxTargets(ast);
20848
- const usedFunctions = /* @__PURE__ */ new Set();
20849
- for (const fn of autoImportable) {
20850
- if (called.has(fn)) usedFunctions.add(fn);
20851
- }
20852
- if (usedFunctions.size > 0) {
20853
- const existing = /* @__PURE__ */ new Set();
20854
- for (const imp of imports) {
20855
- if (importModuleTarget(imp) !== "@vesk/runtime") continue;
20856
- for (const n of extractImportNames(imp)) existing.add(n);
21145
+ const asyncNames = new Set(components.filter((c) => c.isAsync || c.ssrAwait).map((c) => c.name));
21146
+ for (const comp of components) {
21147
+ if (asyncNames.has(comp.name)) continue;
21148
+ const called2 = /* @__PURE__ */ new Map();
21149
+ collectComponentCalls(comp.body, called2);
21150
+ for (const [childName, start] of called2) {
21151
+ if (!asyncNames.has(childName)) continue;
21152
+ const { line, column } = offsetToLineCol2(source, start >= 0 ? start : 0);
21153
+ throw VeskError.asyncChildInSyncParent(comp.name, childName, { file, line, column, code: codeFrame(source, line, column) });
21154
+ }
20857
21155
  }
20858
- const boundLocally = /* @__PURE__ */ new Set();
20859
- for (const imp of imports) {
20860
- for (const pair of importBindingPairs(imp)) boundLocally.add(pair.local);
21156
+ const autoImportable = [
21157
+ "useFetch",
21158
+ "useRouter",
21159
+ "useParams",
21160
+ "usePathname",
21161
+ "useSearchParams",
21162
+ "useNavigate",
21163
+ "defineAction",
21164
+ "Form",
21165
+ "Field",
21166
+ "required",
21167
+ "email",
21168
+ "minLength",
21169
+ "maxLength",
21170
+ "pattern",
21171
+ "custom",
21172
+ "Link",
21173
+ "NavLink",
21174
+ "Outlet",
21175
+ "Redirect",
21176
+ "Image",
21177
+ "Portal",
21178
+ "Experiment",
21179
+ "LoadingIndicator",
21180
+ "useLoadingIndicator",
21181
+ "JsonLd",
21182
+ "ArticleSchema",
21183
+ "ProductSchema",
21184
+ "FAQPageSchema",
21185
+ "BreadcrumbListSchema",
21186
+ "OrganizationSchema",
21187
+ "LocalBusinessSchema",
21188
+ "VideoSchema",
21189
+ "effect",
21190
+ "derived",
21191
+ "untrack",
21192
+ "peek",
21193
+ "tick",
21194
+ "flushSync",
21195
+ "on_destroy",
21196
+ "createContext",
21197
+ "redirect",
21198
+ "permanentRedirect",
21199
+ "notFound",
21200
+ "NotFoundError",
21201
+ "createResource",
21202
+ "getAction",
21203
+ "validateActionInput",
21204
+ "issuesToFieldMap",
21205
+ "isFormAction",
21206
+ "Show",
21207
+ "For",
21208
+ "Switch",
21209
+ "Match",
21210
+ "primitive",
21211
+ "leaf"
21212
+ ];
21213
+ const called = collectCallAndJsxTargets(ast);
21214
+ const usedFunctions = /* @__PURE__ */ new Set();
21215
+ for (const fn of autoImportable) {
21216
+ if (called.has(fn)) usedFunctions.add(fn);
20861
21217
  }
20862
- const missing = [...usedFunctions].filter((f) => !existing.has(f) && !boundLocally.has(f));
20863
- if (missing.length > 0) {
20864
- imports.push(`import { ${missing.join(", ")} } from '@vesk/runtime';`);
21218
+ if (usedFunctions.size > 0) {
21219
+ const existing = /* @__PURE__ */ new Set();
21220
+ for (const imp of imports) {
21221
+ if (importModuleTarget(imp) !== "@vesk/runtime") continue;
21222
+ for (const n of extractImportNames(imp)) existing.add(n);
21223
+ }
21224
+ const boundLocally = /* @__PURE__ */ new Set();
21225
+ for (const imp of imports) {
21226
+ for (const pair of importBindingPairs(imp)) boundLocally.add(pair.local);
21227
+ }
21228
+ const missing = [...usedFunctions].filter((f) => !existing.has(f) && !boundLocally.has(f));
21229
+ if (missing.length > 0) {
21230
+ imports.push(`import { ${missing.join(", ")} } from '@vesk/runtime';`);
21231
+ }
20865
21232
  }
21233
+ return new IRRoot(components, imports, importedNames, staticProps, loadFn, topLevelCode, exportAliases, reexportSources);
21234
+ } finally {
21235
+ currentVskNamespaceLocals = prevNamespaceLocals;
21236
+ currentSourceFile = prevSourceFile;
20866
21237
  }
20867
- return new IRRoot(components, imports, importedNames, staticProps, loadFn, topLevelCode);
20868
21238
  }
20869
- var __vskAnnotations, __slotProps, __propsParam;
21239
+ var __vskAnnotations, __slotProps, __propsParam, currentVskNamespaceLocals, currentSourceFile;
20870
21240
  var init_ir_generator = __esm({
20871
21241
  "../compiler/src/ir-generator.ts"() {
20872
21242
  "use strict";
@@ -20881,6 +21251,7 @@ var init_ir_generator = __esm({
20881
21251
  __vskAnnotations = [];
20882
21252
  __slotProps = null;
20883
21253
  __propsParam = null;
21254
+ currentVskNamespaceLocals = null;
20884
21255
  }
20885
21256
  });
20886
21257
 
@@ -21774,6 +22145,13 @@ function loadRuntimeImports(importStrs) {
21774
22145
  }
21775
22146
  return {};
21776
22147
  }
22148
+ function patternElementName(element) {
22149
+ if (!element) return null;
22150
+ if (element.type === "Identifier") return element.name;
22151
+ if (element.type === "AssignmentPattern" && element.left) return patternElementName(element.left);
22152
+ if (element.type === "RestElement" && element.argument) return patternElementName(element.argument);
22153
+ return null;
22154
+ }
21777
22155
  function evalTopLevelCode(topLevelCode, __vesk) {
21778
22156
  for (const code of topLevelCode) {
21779
22157
  const ast = tryParseTopLevel(code);
@@ -21784,8 +22162,11 @@ function evalTopLevelCode(topLevelCode, __vesk) {
21784
22162
  if (!target) continue;
21785
22163
  if (target.type === "VariableDeclaration") {
21786
22164
  for (const d of target.declarations) {
21787
- if (!d.id || d.id.type !== "Identifier") continue;
21788
- const initSrc = d.init ? code.slice(d.init.start, d.init.end) : "undefined";
22165
+ if (!d.id) continue;
22166
+ const isTrack = d.id.type === "ArrayPattern" && d.id.lazy === true;
22167
+ const names = isTrack ? (d.id.elements || []).map(patternElementName) : d.id.type === "Identifier" ? [d.id.name] : [];
22168
+ if (names.every((n) => n === null)) continue;
22169
+ const initSrc = d.init ? stripTrackDeclMarkers(code.slice(d.init.start, d.init.end), d.init.start, d.init) : "undefined";
21789
22170
  try {
21790
22171
  const keys = Object.keys(__vesk);
21791
22172
  const params = [...keys, "__vesk", "result"];
@@ -21793,7 +22174,10 @@ function evalTopLevelCode(topLevelCode, __vesk) {
21793
22174
  const fn = new Function(...params, body);
21794
22175
  const result = { value: void 0 };
21795
22176
  fn(...keys.map((k) => __vesk[k]), __vesk, result);
21796
- __vesk[d.id.name] = result.value;
22177
+ names.forEach((name, i) => {
22178
+ if (name === null) return;
22179
+ __vesk[name] = isTrack ? Array.isArray(result.value) ? result.value[i] : void 0 : result.value;
22180
+ });
21797
22181
  } catch {
21798
22182
  }
21799
22183
  }
@@ -21803,7 +22187,7 @@ function evalTopLevelCode(topLevelCode, __vesk) {
21803
22187
  const keys = Object.keys(__vesk);
21804
22188
  const params = [...keys, "__vesk"];
21805
22189
  const paramSrc = target.params.length ? code.slice(target.params[0].start, target.params[target.params.length - 1].end) : "";
21806
- const bodySrc = code.slice(target.body.start, target.body.end);
22190
+ const bodySrc = stripTrackDeclMarkers(code.slice(target.body.start, target.body.end), target.body.start, target.body);
21807
22191
  const asyncKw = target.async ? "async " : "";
21808
22192
  const fn = new Function(...params, `__vesk['${target.id.name}'] = ${asyncKw}function ${target.id.name}(${paramSrc}) ${bodySrc};`);
21809
22193
  fn(...keys.map((k) => __vesk[k]), __vesk);
@@ -23367,7 +23751,8 @@ function Form(props, registry, hydrate) {
23367
23751
  return `<form ${attrStr}>${children || ""}</form>`;
23368
23752
  }
23369
23753
  if (hydrate && hydrate.nextElement) {
23370
- let form2 = hydrate.nextElement("form");
23754
+ const skipK = typeof hydrate.takeSkipK === "function" ? hydrate.takeSkipK() : 0;
23755
+ let form2 = hydrate.nextElement("form", skipK);
23371
23756
  if (form2 && !form2.parentNode && hydrate.root) {
23372
23757
  const existing = hydrate.root.querySelector("form");
23373
23758
  if (existing) form2 = existing;
@@ -25750,6 +26135,96 @@ var init_headless = __esm({
25750
26135
  }
25751
26136
  });
25752
26137
 
26138
+ // ../runtime/src/primitive.ts
26139
+ function primitive(fn) {
26140
+ const wrapped = ((props, registry, scope2) => {
26141
+ return fn(props == null ? EMPTY_PROPS : props, registry, scope2);
26142
+ });
26143
+ wrapped.__veskPrimitive = true;
26144
+ return wrapped;
26145
+ }
26146
+ function leaf(fn) {
26147
+ fn.__veskLeaf = true;
26148
+ return fn;
26149
+ }
26150
+ function isPrimitive(value) {
26151
+ return typeof value === "function" && value.__veskPrimitive === true;
26152
+ }
26153
+ function isLeaf(value) {
26154
+ return typeof value === "function" && value.__veskLeaf === true;
26155
+ }
26156
+ function isVeskComponent(value) {
26157
+ return typeof value === "function";
26158
+ }
26159
+ function toDomNode(value) {
26160
+ if (typeof document === "undefined") return value;
26161
+ if (value == null || typeof value === "boolean") return value;
26162
+ if (typeof value.nodeType === "number") {
26163
+ return value;
26164
+ }
26165
+ if (typeof value !== "string") return value;
26166
+ if (value === "") return document.createDocumentFragment();
26167
+ const template = document.createElement("template");
26168
+ template.innerHTML = value;
26169
+ const { content } = template;
26170
+ if (content.childNodes.length === 1) {
26171
+ const only = content.firstChild;
26172
+ content.removeChild(only);
26173
+ return only;
26174
+ }
26175
+ return content;
26176
+ }
26177
+ function isCell2(value) {
26178
+ return typeof value === "object" && value !== null && typeof value.f === "number";
26179
+ }
26180
+ function readDep(dep) {
26181
+ return isCell2(dep) ? get(dep) : dep;
26182
+ }
26183
+ function rerenderNode(node, deps, call) {
26184
+ if (typeof document === "undefined") return node;
26185
+ if (deps.length === 0) return node;
26186
+ let owned = null;
26187
+ let current2 = null;
26188
+ if (Array.isArray(node)) {
26189
+ const roots = node.filter((n) => n && typeof n.nodeType === "number");
26190
+ owned = roots.length ? roots : null;
26191
+ current2 = owned ? owned[0] : null;
26192
+ } else if (node && typeof node.nodeType === "number") {
26193
+ current2 = node;
26194
+ }
26195
+ if (!current2) return node;
26196
+ const liveRange = () => {
26197
+ if (owned) return owned;
26198
+ return current2 && current2.parentNode ? [current2] : null;
26199
+ };
26200
+ let seen = deps.map(readDep);
26201
+ effect(() => {
26202
+ const now2 = deps.map(readDep);
26203
+ if (now2.length === seen.length && now2.every((v, i) => Object.is(v, seen[i]))) return;
26204
+ seen = now2;
26205
+ const old = liveRange();
26206
+ if (!old || !old[0].parentNode) return;
26207
+ const next = toDomNode(call());
26208
+ if (!next || typeof next.nodeType !== "number") return;
26209
+ const fresh = next.nodeType === 11 ? Array.from(next.childNodes) : [next];
26210
+ const parent = old[0].parentNode;
26211
+ for (const freshNode of fresh) parent.insertBefore(freshNode, old[0]);
26212
+ for (const oldNode of old) if (oldNode.parentNode) oldNode.parentNode.removeChild(oldNode);
26213
+ owned = next.nodeType === 11 ? fresh : null;
26214
+ current2 = fresh[0] ?? current2;
26215
+ });
26216
+ return node;
26217
+ }
26218
+ var EMPTY_PROPS;
26219
+ var init_primitive = __esm({
26220
+ "../runtime/src/primitive.ts"() {
26221
+ "use strict";
26222
+ init_ripple_runtime();
26223
+ init_ripple_blocks();
26224
+ EMPTY_PROPS = Object.freeze({});
26225
+ }
26226
+ });
26227
+
25753
26228
  // ../runtime/src/action.ts
25754
26229
  function getActionRegistry() {
25755
26230
  const g2 = globalThis;
@@ -25903,11 +26378,15 @@ __export(index_server_exports, {
25903
26378
  get_server_context: () => get_server_context,
25904
26379
  headers: () => headers,
25905
26380
  isFormAction: () => isFormAction,
26381
+ isLeaf: () => isLeaf,
25906
26382
  isLoadingActive: () => isLoadingActive,
26383
+ isPrimitive: () => isPrimitive,
26384
+ isVeskComponent: () => isVeskComponent,
25907
26385
  is_destroyed: () => is_destroyed,
25908
26386
  isr: () => isr,
25909
26387
  isrConfigToRevalidate: () => isrConfigToRevalidate,
25910
26388
  issuesToFieldMap: () => issuesToFieldMap,
26389
+ leaf: () => leaf,
25911
26390
  locals: () => locals,
25912
26391
  maxLength: () => maxLength,
25913
26392
  minLength: () => minLength,
@@ -25921,12 +26400,14 @@ __export(index_server_exports, {
25921
26400
  permanentRedirect: () => permanentRedirect,
25922
26401
  pop_component: () => pop_component,
25923
26402
  pre_effect: () => pre_effect,
26403
+ primitive: () => primitive,
25924
26404
  push_component: () => push_component,
25925
26405
  readSignedCookie: () => readSignedCookie2,
25926
26406
  redirect: () => redirect,
25927
26407
  removeHook: () => removeHook,
25928
26408
  render: () => render,
25929
26409
  required: () => required,
26410
+ rerenderNode: () => rerenderNode,
25930
26411
  resolveSsrResources: () => resolveSsrResources,
25931
26412
  resume_block: () => resume_block,
25932
26413
  revalidateComponent: () => revalidateComponent,
@@ -25950,6 +26431,7 @@ __export(index_server_exports, {
25950
26431
  set_server_context: () => set_server_context,
25951
26432
  signCookie: () => signCookie2,
25952
26433
  tick: () => tick,
26434
+ toDomNode: () => toDomNode,
25953
26435
  track: () => track,
25954
26436
  unlink_block: () => unlink_block,
25955
26437
  unsignCookie: () => unsignCookie2,
@@ -25988,6 +26470,7 @@ var init_index_server = __esm({
25988
26470
  init_form();
25989
26471
  init_md();
25990
26472
  init_headless();
26473
+ init_primitive();
25991
26474
  init_loading_indicator();
25992
26475
  init_action();
25993
26476
  }
@@ -28417,11 +28900,20 @@ function printWithTypesStripped(ast, code, hadTs = hasTsSyntax(ast)) {
28417
28900
  function transformTopLevelForActions(topLevelCode, mode) {
28418
28901
  const out = [];
28419
28902
  for (const c of topLevelCode) {
28420
- const rewritten = rewriteTopLevelActions(c, mode);
28903
+ const rewritten = rewriteTopLevelActions(stripTopLevelTrackDecls(c), mode);
28421
28904
  if (rewritten !== "") out.push(rewritten);
28422
28905
  }
28423
28906
  return out;
28424
28907
  }
28908
+ function stripTopLevelTrackDecls(code) {
28909
+ let ast;
28910
+ try {
28911
+ ast = parse4(code);
28912
+ } catch {
28913
+ return code;
28914
+ }
28915
+ return stripTrackDeclMarkers(code, 0, ast);
28916
+ }
28425
28917
  function collectActionIds(source) {
28426
28918
  const ids = [];
28427
28919
  const stmts = collectTopLevelStatements(source);
@@ -28477,6 +28969,7 @@ var init_actions = __esm({
28477
28969
  "use strict";
28478
28970
  init_parser();
28479
28971
  init_strip_ts();
28972
+ init_tokens();
28480
28973
  ACTION_PREFIX = "/_vesk/action/";
28481
28974
  }
28482
28975
  });
@@ -28604,6 +29097,39 @@ function simpleGetName(expr) {
28604
29097
  }
28605
29098
  return inner;
28606
29099
  }
29100
+ function untrackBindingArg(expr) {
29101
+ let head = -1;
29102
+ for (const name of BINDING_REF_CALLS) {
29103
+ if (expr.startsWith(`${name}(`)) {
29104
+ head = name.length;
29105
+ break;
29106
+ }
29107
+ }
29108
+ if (head < 0) return expr;
29109
+ const rest = expr.slice(head + 1);
29110
+ if (rest[0] !== "g" || rest[1] !== "e" || rest[2] !== "t" || rest[3] !== "(") return expr;
29111
+ let i = 4;
29112
+ let word = "";
29113
+ for (; i < rest.length; i++) {
29114
+ const c = rest.charCodeAt(i);
29115
+ const ok = c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95 || c === 36;
29116
+ if (!ok) break;
29117
+ word += rest[i];
29118
+ }
29119
+ if (word.length === 0 || rest[i] !== ")") return expr;
29120
+ const after = i + 1;
29121
+ if (rest[after] !== "," && rest[after] !== ")") return expr;
29122
+ return expr.slice(0, head + 1) + word + rest.slice(after);
29123
+ }
29124
+ function trackedRefTarget(expr, tracked2) {
29125
+ const cell = simpleGetName(expr);
29126
+ if (cell !== null) return cell;
29127
+ if (/^[A-Za-z_$][\w$]*$/.test(expr)) {
29128
+ const info = tracked2.get(expr);
29129
+ if (info && info.kind === "cell" && info.cellName === expr) return expr;
29130
+ }
29131
+ return null;
29132
+ }
28607
29133
  function semicolonizeStatement(code) {
28608
29134
  const trimmed = code.trimEnd();
28609
29135
  if (!trimmed || trimmed.endsWith(";") || trimmed.endsWith("}")) return code;
@@ -28702,6 +29228,21 @@ function transformTracked(irNode, tracked2) {
28702
29228
  }
28703
29229
  return context.next();
28704
29230
  },
29231
+ Property(node, context) {
29232
+ if (node.shorthand && node.value && node.value.type === "Identifier" && !node.computed) {
29233
+ const info = context.state.get(node.value.name);
29234
+ if (info && info.kind === "virtual") {
29235
+ return {
29236
+ ...node,
29237
+ shorthand: false,
29238
+ value: callExpr({ type: "Identifier", name: "get" }, [
29239
+ { type: "Identifier", name: info.cellName }
29240
+ ])
29241
+ };
29242
+ }
29243
+ }
29244
+ return context.next();
29245
+ },
28705
29246
  Identifier(node, context) {
28706
29247
  const parent = context.path.at(-1);
28707
29248
  if (parent) {
@@ -28713,6 +29254,8 @@ function transformTracked(irNode, tracked2) {
28713
29254
  return context.next();
28714
29255
  if (parent.type === "Property" && parent.value === node && parent.key && parent.key.type === "Identifier" && parent.key.name === "into")
28715
29256
  return context.next();
29257
+ if (parent.type === "Property" && parent.key === node && !parent.computed && !parent.shorthand)
29258
+ return context.next();
28716
29259
  if (parent.type === "MemberExpression" && !parent.computed && parent.object === node && parent.property && parent.property.type === "Identifier" && parent.property.name === "set")
28717
29260
  return context.next();
28718
29261
  }
@@ -28739,6 +29282,28 @@ function collectTrackedNames(body) {
28739
29282
  }
28740
29283
  return names;
28741
29284
  }
29285
+ function collectTrackedDeps(value, tracked2) {
29286
+ const ast = value?.ast;
29287
+ if (!ast || typeof ast !== "object" || tracked2.size === 0) return [];
29288
+ const found = [];
29289
+ const seen = /* @__PURE__ */ new Set();
29290
+ walk4(ast, tracked2, {
29291
+ Identifier(node, context) {
29292
+ const parent = context.path.at(-1);
29293
+ if (parent) {
29294
+ if (parent.type === "MemberExpression" && !parent.computed && parent.property === node) return context.next();
29295
+ if (parent.type === "Property" && parent.key === node) return context.next();
29296
+ }
29297
+ const info = context.state.get(node.name);
29298
+ if (info && !seen.has(node.name)) {
29299
+ seen.add(node.name);
29300
+ found.push(node.name);
29301
+ }
29302
+ return context.next();
29303
+ }
29304
+ });
29305
+ return found;
29306
+ }
28742
29307
  function transformTrackedInit(init, tracked2) {
28743
29308
  if (!init) return init;
28744
29309
  let expr = null;
@@ -28932,8 +29497,9 @@ function emitStatic(ctx2, node, tracked2, effectsVar, skipK = 0, regionBudget) {
28932
29497
  const target = attr.target || "";
28933
29498
  const isEvent2 = target.startsWith("on") && target.length > 2;
28934
29499
  if (target === "ref") {
28935
- const expr = transformTracked(attr.expression, tracked2);
28936
- ctx2.push(`(${expr})(${ssrEl});`);
29500
+ const expr = untrackBindingArg(transformTracked(attr.expression, tracked2));
29501
+ const cell = trackedRefTarget(expr, tracked2);
29502
+ ctx2.push(cell !== null ? `set(${cell}, ${ssrEl});` : `(${expr})(${ssrEl});`);
28937
29503
  } else if (isEvent2) {
28938
29504
  const eventName = target.slice(2).toLowerCase();
28939
29505
  const handler = transformTracked(attr.expression, tracked2);
@@ -28990,8 +29556,9 @@ function emitStatic(ctx2, node, tracked2, effectsVar, skipK = 0, regionBudget) {
28990
29556
  const target = attr.target || "";
28991
29557
  const isEvent2 = target.startsWith("on") && target.length > 2;
28992
29558
  if (target === "ref") {
28993
- const expr = transformTracked(attr.expression, tracked2);
28994
- ctx2.push(`(${expr})(${el});`);
29559
+ const expr = untrackBindingArg(transformTracked(attr.expression, tracked2));
29560
+ const cell = trackedRefTarget(expr, tracked2);
29561
+ ctx2.push(cell !== null ? `set(${cell}, ${el});` : `(${expr})(${el});`);
28995
29562
  } else if (isEvent2) {
28996
29563
  const eventName = target.slice(2).toLowerCase();
28997
29564
  const handler = transformTracked(attr.expression, tracked2);
@@ -29185,19 +29752,29 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
29185
29752
  const calleeExpr = node.calleeExpr ? `(${node.calleeExpr})` : null;
29186
29753
  const slotChildren = node.children.filter((c) => c instanceof PropSlot);
29187
29754
  const regChildren = node.children.filter((c) => !(c instanceof PropSlot));
29188
- const callArgs = () => `{ ${propsEntries.join(", ")} }`;
29755
+ const plainTarget = !!(calleeExpr || ctx2.importedNames.has(node.componentName)) && !ctx2.selfClaimNames.has(node.componentName);
29756
+ const trackedDeps = [];
29757
+ if (plainTarget) {
29758
+ for (const p of node.props) {
29759
+ if (typeof p.value === "string") continue;
29760
+ for (const d of collectTrackedDeps(p.value, tracked2)) if (!trackedDeps.includes(d)) trackedDeps.push(d);
29761
+ }
29762
+ for (const sp of node.spreadProps) {
29763
+ for (const d of collectTrackedDeps(sp, tracked2)) if (!trackedDeps.includes(d)) trackedDeps.push(d);
29764
+ }
29765
+ }
29766
+ const callArgs = () => plainTarget ? `reactiveProps({ ${propsEntries.join(", ")} })` : `{ ${propsEntries.join(", ")} }`;
29189
29767
  if (ctx2.hydrate) {
29190
29768
  const access = calleeExpr ?? (ctx2.importedNames.has(node.componentName) ? node.componentName : `__components[${JSON.stringify(node.componentName)}]`);
29191
29769
  if (!calleeExpr && !ctx2.importedNames.has(node.componentName)) {
29192
29770
  ctx2.push(`if (${access} == null) throw new Error(${JSON.stringify(`Component "${node.componentName}" was not found while rendering. Declare it with the \`component\` keyword, import it, or register it in the component registry.`)});`);
29193
29771
  }
29194
- const plainTarget = !!(calleeExpr || ctx2.importedNames.has(node.componentName)) && !ctx2.selfClaimNames.has(node.componentName);
29195
29772
  const walkerArg = ctx2.walker;
29196
29773
  const promptExpr = ctx2.markerless && (regionBudget || skipK > 0) ? markerlessSkipExpr(regionBudget, skipK) : null;
29197
29774
  const maybeReplace = (v2) => {
29198
29775
  if (!plainTarget) return;
29199
29776
  const claim = promptExpr ? `${walkerArg}.claimOnly(undefined, ${promptExpr})` : `${walkerArg}.claimOnly()`;
29200
- ctx2.push(`if (${v2} && ${v2}.parentNode == null && ${v2}.nodeType !== 11) { const __sr = ${claim}; if (__sr && __sr.parentNode) __sr.parentNode.replaceChild(${v2}, __sr); }`);
29777
+ ctx2.push(`if (${v2} && ${v2}.parentNode == null) { if (${v2}.nodeType === 11) { const __cnt = ${v2}.childNodes.length; let __sr = null; for (let __i = 0; __i < __cnt; __i++) { const __c = ${claim}; if (__c && __c.parentNode) { if (__sr) { __c.remove(); } else { __sr = __c; } } } if (__sr) { const __p = __sr.parentNode; while (${v2}.firstChild) __p.insertBefore(${v2}.firstChild, __sr); __p.removeChild(__sr); } } else { const __sr = ${claim}; if (__sr && __sr.parentNode) __sr.parentNode.replaceChild(${v2}, __sr); } }`);
29201
29778
  if (regionBudget && ctx2.markerless) ctx2.push(`${regionBudget} = 0;`);
29202
29779
  };
29203
29780
  const maybeRetire = () => {
@@ -29213,7 +29790,7 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
29213
29790
  const frag = ctx2.n();
29214
29791
  const wipeMount = ctx2.linkNames.has(node.componentName);
29215
29792
  const savedHydrate = ctx2.hydrate;
29216
- if (wipeMount) ctx2.hydrate = false;
29793
+ if (wipeMount || ctx2.selfClaimNames.has(node.componentName)) ctx2.hydrate = false;
29217
29794
  ctx2.push(`const ${frag} = (() => { const $f = document.createDocumentFragment();`);
29218
29795
  const savedEffects = ctx2.effects;
29219
29796
  ctx2.effects = [];
@@ -29232,10 +29809,15 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
29232
29809
  }
29233
29810
  ctx2.push(`let ${v} = undefined;`);
29234
29811
  ctx2.push(`if (__hydrate) __hydrate.childFrame = (__hydrate.childFrame || 0) + 1;`);
29235
- ctx2.push(`try { ${v} = ${awaitKw}${access}(${callArgs()}, __registry, ${walkerArg}); } finally { if (__hydrate) __hydrate.childFrame--; }`);
29812
+ ctx2.push(`try { ${v} = toDomNode(${awaitKw}${access}(${callArgs()}, __registry, ${walkerArg})); } finally { if (__hydrate) __hydrate.childFrame--; }`);
29813
+ const rootsVar = trackedDeps.length > 0 ? ctx2.n() : null;
29814
+ if (rootsVar) ctx2.push(`const ${rootsVar} = ${v} && ${v}.nodeType === 11 ? Array.from(${v}.childNodes) : [${v}];`);
29236
29815
  if (ctx2.markerless && promptExpr && !plainTarget && regionBudget) ctx2.push(`${regionBudget} = 0;`);
29237
29816
  maybeReplace(v);
29238
29817
  maybeRetire();
29818
+ if (trackedDeps.length > 0) {
29819
+ ctx2.push(`rerenderNode(${rootsVar}, [${trackedDeps.join(", ")}], () => ${awaitKw}${access}(${callArgs()}, __registry, ${walkerArg}));`);
29820
+ }
29239
29821
  return v;
29240
29822
  } else {
29241
29823
  for (const slot of slotChildren) {
@@ -29257,12 +29839,18 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
29257
29839
  propsEntries.push(`children: ${frag}`);
29258
29840
  }
29259
29841
  if (calleeExpr) {
29260
- ctx2.push(`const ${v} = ${calleeExpr}(${callArgs()});`);
29842
+ ctx2.push(`const ${v} = toDomNode(${calleeExpr}(${callArgs()}));`);
29261
29843
  } else if (ctx2.importedNames.has(node.componentName)) {
29262
- ctx2.push(`const ${v} = ${awaitKw}${node.componentName}(${callArgs()});`);
29844
+ ctx2.push(`const ${v} = toDomNode(${awaitKw}${node.componentName}(${callArgs()}));`);
29263
29845
  } else {
29264
29846
  ctx2.push(`if (${compPrefix}[${JSON.stringify(node.componentName)}] == null) throw new Error(${JSON.stringify(`Component "${node.componentName}" was not found while rendering. Declare it with the \`component\` keyword, import it, or register it in the component registry.`)});`);
29265
- ctx2.push(`const ${v} = ${awaitKw}${compPrefix}[${JSON.stringify(node.componentName)}](${callArgs()});`);
29847
+ ctx2.push(`const ${v} = toDomNode(${awaitKw}${compPrefix}[${JSON.stringify(node.componentName)}](${callArgs()}));`);
29848
+ }
29849
+ if (trackedDeps.length > 0) {
29850
+ const calleeRef = calleeExpr ?? (ctx2.importedNames.has(node.componentName) ? node.componentName : `${compPrefix}[${JSON.stringify(node.componentName)}]`);
29851
+ const rootsVar2 = ctx2.n();
29852
+ ctx2.push(`const ${rootsVar2} = ${v} && ${v}.nodeType === 11 ? Array.from(${v}.childNodes) : [${v}];`);
29853
+ ctx2.push(`rerenderNode(${rootsVar2}, [${trackedDeps.join(", ")}], () => ${awaitKw}${calleeRef}(${callArgs()}));`);
29266
29854
  }
29267
29855
  }
29268
29856
  return v;
@@ -30348,7 +30936,7 @@ function emitClientFromIR(ir, options) {
30348
30936
  }
30349
30937
  }
30350
30938
  const exportCode = exportLines.join("\n");
30351
- const runtimeNames = ["track", "get", "set", "destroy_block", "getActiveComponent", "setActiveComponent", "reactiveProps", "applyStyle"];
30939
+ const runtimeNames = ["track", "get", "set", "destroy_block", "getActiveComponent", "setActiveComponent", "reactiveProps", "applyStyle", "toDomNode", "rerenderNode"];
30352
30940
  if (ir.components.some((c) => !isStaticIR(c.body))) runtimeNames.push("effect");
30353
30941
  for (const name of usedRuntimeBindings(ir)) runtimeNames.push(name);
30354
30942
  for (const name of ["derived"]) {
@@ -30409,14 +30997,18 @@ function compileClientBoth(source, _componentName, sourcePath2, opts) {
30409
30997
  }
30410
30998
  const alloc = nameAllocFor(sourcePath2);
30411
30999
  const comp = emitClientFromIR(ir, { forceClient: true, nameAllocator: alloc });
30412
- if (opts?.skipHyd) return { comp, hyd: "", name };
31000
+ const aliases = vskRegistryAliases(ir.imports, ir.exportAliases);
31001
+ const reexportPaths = sourcePath2 ? collectVskReexportPaths(ir.reexportSources, sourcePath2) : [];
31002
+ if (opts?.skipHyd) return { comp, hyd: "", name, aliases, reexportPaths };
30413
31003
  return {
30414
31004
  comp,
30415
31005
  hyd: emitClientFromIR(irHyd, { forceClient: true, hydrate: true, includeTopLevel: false, nameAllocator: alloc, markerless: opts?.markerless !== false }),
30416
- name
31006
+ name,
31007
+ aliases,
31008
+ reexportPaths
30417
31009
  };
30418
31010
  }
30419
- var NON_BUBBLING_EVENTS, Ctx, PROPERTY_ATTRS;
31011
+ var BINDING_REF_CALLS, NON_BUBBLING_EVENTS, Ctx, PROPERTY_ATTRS;
30420
31012
  var init_client_codegen = __esm({
30421
31013
  "../compiler/src/client-codegen.ts"() {
30422
31014
  "use strict";
@@ -30428,8 +31020,10 @@ var init_client_codegen = __esm({
30428
31020
  init_module_imports();
30429
31021
  init_scan();
30430
31022
  init_tokens();
31023
+ init_vsk_imports();
30431
31024
  init_md_inline();
30432
31025
  init_strip_ts();
31026
+ BINDING_REF_CALLS = ["bindValue", "bindChecked", "bindGroup"];
30433
31027
  NON_BUBBLING_EVENTS = /* @__PURE__ */ new Set([
30434
31028
  "focus",
30435
31029
  "blur",
@@ -30965,7 +31559,8 @@ function buildComponentEntries(irRoot) {
30965
31559
  const importedNames = /* @__PURE__ */ new Set([...runtimeNames, ...localValueNames, ...topValueNames]);
30966
31560
  const hasTracked = irRoot.components.some((c) => c.body.some((n) => n instanceof TrackDecl));
30967
31561
  const extraNames = hasTracked ? ["get", "set", "track"] : [];
30968
- const allNames = [.../* @__PURE__ */ new Set([...runtimeNames, ...topNames, ...extraNames, ...localValueNames])];
31562
+ const vskValueNames = vskImportValueNames(irRoot.imports);
31563
+ const allNames = [.../* @__PURE__ */ new Set([...runtimeNames, ...topNames, ...extraNames, ...localValueNames, ...vskValueNames])];
30969
31564
  const scopeDecl = allNames.length > 0 ? `const { ${allNames.join(", ")} } = __vesk;
30970
31565
  ` : "";
30971
31566
  setVskImportedNames(importedNames);
@@ -31006,6 +31601,7 @@ var init_server_jsgen = __esm({
31006
31601
  init_scan();
31007
31602
  init_server_utils();
31008
31603
  init_module_imports();
31604
+ init_vsk_imports();
31009
31605
  __currentCompName = "";
31010
31606
  }
31011
31607
  });
@@ -31078,7 +31674,11 @@ function compileFileInternal(source, sourcePath2, seenImportFiles) {
31078
31674
  const __vesk = loadRuntimeImports(ir.imports);
31079
31675
  applyLocalModuleImports(__vesk, ir.imports, sourcePath2);
31080
31676
  if (sourcePath2) {
31081
- for (const importPath of collectVskImportPaths(ir.imports, sourcePath2)) {
31677
+ const vskPaths = [
31678
+ ...collectVskImportPaths(ir.imports, sourcePath2),
31679
+ ...collectVskReexportPaths(ir.reexportSources, sourcePath2)
31680
+ ];
31681
+ for (const importPath of vskPaths) {
31082
31682
  if (seenImportFiles.has(importPath)) continue;
31083
31683
  seenImportFiles.add(importPath);
31084
31684
  let importedSrc;
@@ -31098,6 +31698,7 @@ function compileFileInternal(source, sourcePath2, seenImportFiles) {
31098
31698
  }
31099
31699
  }
31100
31700
  evalTopLevelCode(transformTopLevelForActions(ir.topLevelCode, "server"), __vesk);
31701
+ applyVskRegistryAliases(componentMap, vskRegistryAliases(ir.imports, ir.exportAliases));
31101
31702
  for (const name of ownComponentNames) {
31102
31703
  const fn = componentMap.get(name);
31103
31704
  if (fn && !fn.__veskScope) fn.__veskScope = __vesk;
@@ -34067,7 +34668,7 @@ function unwrapMaybeCell2(v) {
34067
34668
  }
34068
34669
  return v;
34069
34670
  }
34070
- function isCell2(v) {
34671
+ function isCell3(v) {
34071
34672
  return v !== null && typeof v === "object" && typeof v.get === "function";
34072
34673
  }
34073
34674
  function escapeHtml7(s) {
@@ -36072,7 +36673,7 @@ function Md2(props, _registry, hydrate) {
36072
36673
  if (propFg && propFg !== "none")
36073
36674
  wrapperParts.push(`--md-code-fg:${propFg}`);
36074
36675
  const wrapperStyle = wrapperParts.length > 0 ? escapeHtml7(wrapperParts.join(";")) : "";
36075
- const reactive = isCell2(contentCell);
36676
+ const reactive = isCell3(contentCell);
36076
36677
  const pathMode = isPublicMarkdownPath2(content);
36077
36678
  if (mdIsSSR2()) {
36078
36679
  const attrs = className ? ` class="${escapeHtml7(className)}"` : "";
@@ -36733,6 +37334,21 @@ var init_errors2 = __esm({
36733
37334
  tip: isBuiltin ? `"${name}" is a Vesk built-in. Use it directly \u2014 no manual import needed.` : ""
36734
37335
  });
36735
37336
  }
37337
+ static vskNamespaceTag(context = {}) {
37338
+ return new _VeskError("Namespace imports are not supported for `.vsk` modules.", {
37339
+ ...context,
37340
+ code: context.code || "V0410",
37341
+ suggestions: [
37342
+ "Import the component by name: import { MyIcon } from './icons.vsk'",
37343
+ "Rename on import: import { MyIcon as Icon } from './icons.vsk'"
37344
+ ],
37345
+ nextSteps: [
37346
+ "A `.vsk` component is a registry entry keyed by its name, not a module namespace object, so `<ns.Icon />` cannot be resolved.",
37347
+ "If you need a namespace object, import from a `.ts`/`.js` module instead \u2014 those are real ES modules."
37348
+ ],
37349
+ tip: "A `.vsk` module exposes its components as named exports; use a named or renamed import rather than `import * as ns`."
37350
+ });
37351
+ }
36736
37352
  static classDecl(context = {}) {
36737
37353
  return new _VeskError("class declarations are not supported inside Vesk components.", {
36738
37354
  ...context,
@@ -39698,6 +40314,7 @@ init_server_jsgen();
39698
40314
  // ../compiler/src/precompile-runtime.ts
39699
40315
  init_ir();
39700
40316
  init_server_utils();
40317
+ init_vsk_imports();
39701
40318
  var IR_CLASSES = [
39702
40319
  ["Expression", Expression.prototype],
39703
40320
  ["IRRoot", IRRoot.prototype],
@@ -39784,7 +40401,11 @@ function precompileFileInternal(source, sourcePath2, seenImportFiles) {
39784
40401
  const bindings = sourcePath2 !== void 0 ? collectModuleBundle(ir.imports, dirname6(sourcePath2), collector) : [];
39785
40402
  const subFiles = [];
39786
40403
  if (sourcePath2 !== void 0) {
39787
- for (const importPath of collectVskImportPaths(ir.imports, sourcePath2)) {
40404
+ const vskPaths = [
40405
+ ...collectVskImportPaths(ir.imports, sourcePath2),
40406
+ ...collectVskReexportPaths(ir.reexportSources, sourcePath2)
40407
+ ];
40408
+ for (const importPath of vskPaths) {
39788
40409
  if (seenImportFiles.has(importPath)) continue;
39789
40410
  seenImportFiles.add(importPath);
39790
40411
  try {
@@ -40921,6 +41542,31 @@ function extractCompiledNodes(code, isTarget) {
40921
41542
  function isModuleLevel(node) {
40922
41543
  return node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
40923
41544
  }
41545
+ function nativeLibraryImportStubs(code) {
41546
+ let ast;
41547
+ try {
41548
+ ast = parse4(code);
41549
+ } catch {
41550
+ return "";
41551
+ }
41552
+ const body = ast.body ?? [];
41553
+ const bindings = [];
41554
+ for (const node of body) {
41555
+ if (node?.type !== "ImportDeclaration") continue;
41556
+ const src2 = node.source?.value;
41557
+ if (typeof src2 !== "string" || !src2.startsWith("@vesk/") || src2.startsWith("@vesk/runtime")) continue;
41558
+ for (const spec of node.specifiers ?? []) {
41559
+ if (typeof spec?.local?.name === "string") bindings.push([spec.local.name, src2]);
41560
+ }
41561
+ }
41562
+ if (bindings.length === 0) return "";
41563
+ const lines = bindings.map(([local, spec]) => {
41564
+ const message = `web preview: native library "${spec}" has no browser equivalent on the web (dev-only) \u2014 binding "${local}" cannot be provided in vesk dev --web. Build for Android to use it.`;
41565
+ const thrower = `throw Object.assign(new Error(${JSON.stringify(message)}), { __veskPreviewMissing: ${JSON.stringify(spec)} })`;
41566
+ return `const ${local} = new Proxy(function () {}, { get: function () { ${thrower}; }, apply: function () { ${thrower}; }, construct: function () { ${thrower}; } });`;
41567
+ });
41568
+ return lines.join("\n") + "\n\n";
41569
+ }
40924
41570
  function demoteExports(code) {
40925
41571
  let ast;
40926
41572
  try {
@@ -41254,7 +41900,7 @@ async function generateClientBundle(routeTree, appDir, componentMap, options) {
41254
41900
  }
41255
41901
  const namesBefore = cache2 ? new Set(runtimeImportNames) : null;
41256
41902
  const importedPaths = resolveVskImports(filePath, (p, n) => compileFile2(p, n, output, imports));
41257
- const { comp: rawComp, hyd: rawHyd, name: actualName } = compileClientBoth(src2, null, filePath);
41903
+ const { comp: rawComp, hyd: rawHyd, name: actualName, aliases, reexportPaths } = compileClientBoth(src2, null, filePath);
41258
41904
  const compWithImports = rawComp ? stripExports(stripVskImports(stripRuntimeImport(rawComp))) : "";
41259
41905
  const hydWithImports = rawHyd ? stripExports(stripVskImports(stripRuntimeImport(rawHyd))) : "";
41260
41906
  const compSpecs = [];
@@ -41274,6 +41920,11 @@ async function generateClientBundle(routeTree, appDir, componentMap, options) {
41274
41920
  output.push(`Object.defineProperty(__components, ${JSON.stringify(resolvedName)}, { get: () => __components[${JSON.stringify(actualName)}], configurable: true });`);
41275
41921
  output.push(`Object.defineProperty(__hydrators, ${JSON.stringify(resolvedName)}, { get: () => __hydrators[${JSON.stringify(actualName)}], configurable: true });`);
41276
41922
  }
41923
+ for (const alias of aliases || []) {
41924
+ output.push(`Object.defineProperty(__components, ${JSON.stringify(alias.exported)}, { get: () => __components[${JSON.stringify(alias.local)}], configurable: true });`);
41925
+ output.push(`Object.defineProperty(__hydrators, ${JSON.stringify(alias.exported)}, { get: () => __hydrators[${JSON.stringify(alias.local)}], configurable: true });`);
41926
+ }
41927
+ for (const reexportPath of reexportPaths || []) compileFile2(reexportPath, null, output, imports);
41277
41928
  if (cache2 && namesBefore) {
41278
41929
  const st = statSync3(filePath);
41279
41930
  cache2.files.set(filePath, {
@@ -41411,7 +42062,7 @@ ${entry.code}
41411
42062
  const err = e;
41412
42063
  console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
41413
42064
  const stripped = demoteExports(removeCompiledNodes(entry.code, isAnyImport));
41414
- finalCode = chunkIIFE(stripped);
42065
+ finalCode = chunkIIFE(nativeLibraryImportStubs(entry.code) + stripped);
41415
42066
  } finally {
41416
42067
  try {
41417
42068
  rmSync(tmpBase, { recursive: true, force: true });
@@ -41419,7 +42070,7 @@ ${entry.code}
41419
42070
  }
41420
42071
  }
41421
42072
  } else {
41422
- finalCode = chunkIIFE(entry.code);
42073
+ finalCode = chunkIIFE(demoteExports(entry.code));
41423
42074
  }
41424
42075
  chunks.push({ name: entry.name, code: finalCode });
41425
42076
  }
@@ -41628,7 +42279,7 @@ function appendHmrGlobals(code) {
41628
42279
  return code + "globalThis.__vesk_hmr_eval = (code, n) => {\n if (!n || n !== globalThis.__vesk_hmr_nonce) throw new Error('vesk hmr: invalid nonce');\n return eval(code);\n};\n";
41629
42280
  }
41630
42281
  async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, importRuntime, runtimeImportNames, routeDataCache) {
41631
- const baseRuntimeImports = ["createFileRouter", "get", "set", "effect", "track", "destroy_block", "getActiveComponent", "setActiveComponent", "NavLink", "Link", "reactiveProps", "matchRoute", "ensureChunk"];
42282
+ const baseRuntimeImports = ["createFileRouter", "get", "set", "effect", "track", "destroy_block", "getActiveComponent", "setActiveComponent", "NavLink", "Link", "reactiveProps", "matchRoute", "ensureChunk", "toDomNode", "rerenderNode"];
41632
42283
  const allRuntimeImports = runtimeImportNames && runtimeImportNames.size > 0 ? [.../* @__PURE__ */ new Set([...baseRuntimeImports, ...runtimeImportNames])] : baseRuntimeImports;
41633
42284
  const runtimeGlobals = [
41634
42285
  "reconcile",
@@ -42948,6 +43599,7 @@ init_server_utils();
42948
43599
  init_module_imports();
42949
43600
  init_scan();
42950
43601
  init_tokens();
43602
+ init_vsk_imports();
42951
43603
  init_md_inline();
42952
43604
  init_strip_ts();
42953
43605
  import { walk as walk6 } from "zimmerframe";
@@ -42971,6 +43623,47 @@ function simpleGetName2(expr) {
42971
43623
  }
42972
43624
  return inner;
42973
43625
  }
43626
+ var BINDING_REF_CALLS2 = ["bindValue", "bindChecked", "bindGroup"];
43627
+ function untrackBindingArg2(expr) {
43628
+ let head = -1;
43629
+ for (const name of BINDING_REF_CALLS2) {
43630
+ if (expr.startsWith(`${name}(`)) {
43631
+ head = name.length;
43632
+ break;
43633
+ }
43634
+ }
43635
+ if (head < 0)
43636
+ return expr;
43637
+ const rest = expr.slice(head + 1);
43638
+ if (rest[0] !== "g" || rest[1] !== "e" || rest[2] !== "t" || rest[3] !== "(")
43639
+ return expr;
43640
+ let i = 4;
43641
+ let word = "";
43642
+ for (; i < rest.length; i++) {
43643
+ const c = rest.charCodeAt(i);
43644
+ const ok = c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 95 || c === 36;
43645
+ if (!ok)
43646
+ break;
43647
+ word += rest[i];
43648
+ }
43649
+ if (word.length === 0 || rest[i] !== ")")
43650
+ return expr;
43651
+ const after = i + 1;
43652
+ if (rest[after] !== "," && rest[after] !== ")")
43653
+ return expr;
43654
+ return expr.slice(0, head + 1) + word + rest.slice(after);
43655
+ }
43656
+ function trackedRefTarget2(expr, tracked2) {
43657
+ const cell = simpleGetName2(expr);
43658
+ if (cell !== null)
43659
+ return cell;
43660
+ if (/^[A-Za-z_$][\w$]*$/.test(expr)) {
43661
+ const info = tracked2.get(expr);
43662
+ if (info && info.kind === "cell" && info.cellName === expr)
43663
+ return expr;
43664
+ }
43665
+ return null;
43666
+ }
42974
43667
  function semicolonizeStatement2(code) {
42975
43668
  const trimmed = code.trimEnd();
42976
43669
  if (!trimmed || trimmed.endsWith(";") || trimmed.endsWith("}"))
@@ -43077,6 +43770,21 @@ function transformTracked2(irNode, tracked2) {
43077
43770
  }
43078
43771
  return context.next();
43079
43772
  },
43773
+ Property(node, context) {
43774
+ if (node.shorthand && node.value && node.value.type === "Identifier" && !node.computed) {
43775
+ const info = context.state.get(node.value.name);
43776
+ if (info && info.kind === "virtual") {
43777
+ return {
43778
+ ...node,
43779
+ shorthand: false,
43780
+ value: callExpr2({ type: "Identifier", name: "get" }, [
43781
+ { type: "Identifier", name: info.cellName }
43782
+ ])
43783
+ };
43784
+ }
43785
+ }
43786
+ return context.next();
43787
+ },
43080
43788
  Identifier(node, context) {
43081
43789
  const parent = context.path.at(-1);
43082
43790
  if (parent) {
@@ -43088,6 +43796,8 @@ function transformTracked2(irNode, tracked2) {
43088
43796
  return context.next();
43089
43797
  if (parent.type === "Property" && parent.value === node && parent.key && parent.key.type === "Identifier" && parent.key.name === "into")
43090
43798
  return context.next();
43799
+ if (parent.type === "Property" && parent.key === node && !parent.computed && !parent.shorthand)
43800
+ return context.next();
43091
43801
  if (parent.type === "MemberExpression" && !parent.computed && parent.object === node && parent.property && parent.property.type === "Identifier" && parent.property.name === "set")
43092
43802
  return context.next();
43093
43803
  }
@@ -43115,6 +43825,31 @@ function collectTrackedNames2(body) {
43115
43825
  }
43116
43826
  return names;
43117
43827
  }
43828
+ function collectTrackedDeps2(value, tracked2) {
43829
+ const ast = value?.ast;
43830
+ if (!ast || typeof ast !== "object" || tracked2.size === 0)
43831
+ return [];
43832
+ const found = [];
43833
+ const seen = /* @__PURE__ */ new Set();
43834
+ walk6(ast, tracked2, {
43835
+ Identifier(node, context) {
43836
+ const parent = context.path.at(-1);
43837
+ if (parent) {
43838
+ if (parent.type === "MemberExpression" && !parent.computed && parent.property === node)
43839
+ return context.next();
43840
+ if (parent.type === "Property" && parent.key === node)
43841
+ return context.next();
43842
+ }
43843
+ const info = context.state.get(node.name);
43844
+ if (info && !seen.has(node.name)) {
43845
+ seen.add(node.name);
43846
+ found.push(node.name);
43847
+ }
43848
+ return context.next();
43849
+ }
43850
+ });
43851
+ return found;
43852
+ }
43118
43853
  function transformTrackedInit2(init, tracked2) {
43119
43854
  if (!init)
43120
43855
  return init;
@@ -43451,8 +44186,9 @@ function emitStatic2(ctx2, node, tracked2, effectsVar, skipK = 0, regionBudget)
43451
44186
  const target = attr.target || "";
43452
44187
  const isEvent2 = target.startsWith("on") && target.length > 2;
43453
44188
  if (target === "ref") {
43454
- const expr = transformTracked2(attr.expression, tracked2);
43455
- ctx2.push(`(${expr})(${ssrEl});`);
44189
+ const expr = untrackBindingArg2(transformTracked2(attr.expression, tracked2));
44190
+ const cell = trackedRefTarget2(expr, tracked2);
44191
+ ctx2.push(cell !== null ? `set(${cell}, ${ssrEl});` : `(${expr})(${ssrEl});`);
43456
44192
  } else if (isEvent2) {
43457
44193
  const eventName = target.slice(2).toLowerCase();
43458
44194
  const handler = transformTracked2(attr.expression, tracked2);
@@ -43510,8 +44246,9 @@ function emitStatic2(ctx2, node, tracked2, effectsVar, skipK = 0, regionBudget)
43510
44246
  const target = attr.target || "";
43511
44247
  const isEvent2 = target.startsWith("on") && target.length > 2;
43512
44248
  if (target === "ref") {
43513
- const expr = transformTracked2(attr.expression, tracked2);
43514
- ctx2.push(`(${expr})(${el});`);
44249
+ const expr = untrackBindingArg2(transformTracked2(attr.expression, tracked2));
44250
+ const cell = trackedRefTarget2(expr, tracked2);
44251
+ ctx2.push(cell !== null ? `set(${cell}, ${el});` : `(${expr})(${el});`);
43515
44252
  } else if (isEvent2) {
43516
44253
  const eventName = target.slice(2).toLowerCase();
43517
44254
  const handler = transformTracked2(attr.expression, tracked2);
@@ -43730,20 +44467,35 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
43730
44467
  const calleeExpr = node.calleeExpr ? `(${node.calleeExpr})` : null;
43731
44468
  const slotChildren = node.children.filter((c) => c instanceof PropSlot);
43732
44469
  const regChildren = node.children.filter((c) => !(c instanceof PropSlot));
43733
- const callArgs = () => `{ ${propsEntries.join(", ")} }`;
44470
+ const plainTarget = !!(calleeExpr || ctx2.importedNames.has(node.componentName)) && !ctx2.selfClaimNames.has(node.componentName);
44471
+ const trackedDeps = [];
44472
+ if (plainTarget) {
44473
+ for (const p of node.props) {
44474
+ if (typeof p.value === "string")
44475
+ continue;
44476
+ for (const d of collectTrackedDeps2(p.value, tracked2))
44477
+ if (!trackedDeps.includes(d))
44478
+ trackedDeps.push(d);
44479
+ }
44480
+ for (const sp of node.spreadProps) {
44481
+ for (const d of collectTrackedDeps2(sp, tracked2))
44482
+ if (!trackedDeps.includes(d))
44483
+ trackedDeps.push(d);
44484
+ }
44485
+ }
44486
+ const callArgs = () => plainTarget ? `reactiveProps({ ${propsEntries.join(", ")} })` : `{ ${propsEntries.join(", ")} }`;
43734
44487
  if (ctx2.hydrate) {
43735
44488
  const access = calleeExpr ?? (ctx2.importedNames.has(node.componentName) ? node.componentName : `__components[${JSON.stringify(node.componentName)}]`);
43736
44489
  if (!calleeExpr && !ctx2.importedNames.has(node.componentName)) {
43737
44490
  ctx2.push(`if (${access} == null) throw new Error(${JSON.stringify(`Component "${node.componentName}" was not found while rendering. Declare it with the \`component\` keyword, import it, or register it in the component registry.`)});`);
43738
44491
  }
43739
- const plainTarget = !!(calleeExpr || ctx2.importedNames.has(node.componentName)) && !ctx2.selfClaimNames.has(node.componentName);
43740
44492
  const walkerArg = ctx2.walker;
43741
44493
  const promptExpr = ctx2.markerless && (regionBudget || skipK > 0) ? markerlessSkipExpr2(regionBudget, skipK) : null;
43742
44494
  const maybeReplace = (v2) => {
43743
44495
  if (!plainTarget)
43744
44496
  return;
43745
44497
  const claim = promptExpr ? `${walkerArg}.claimOnly(undefined, ${promptExpr})` : `${walkerArg}.claimOnly()`;
43746
- ctx2.push(`if (${v2} && ${v2}.parentNode == null && ${v2}.nodeType !== 11) { const __sr = ${claim}; if (__sr && __sr.parentNode) __sr.parentNode.replaceChild(${v2}, __sr); }`);
44498
+ ctx2.push(`if (${v2} && ${v2}.parentNode == null) { if (${v2}.nodeType === 11) { const __cnt = ${v2}.childNodes.length; let __sr = null; for (let __i = 0; __i < __cnt; __i++) { const __c = ${claim}; if (__c && __c.parentNode) { if (__sr) { __c.remove(); } else { __sr = __c; } } } if (__sr) { const __p = __sr.parentNode; while (${v2}.firstChild) __p.insertBefore(${v2}.firstChild, __sr); __p.removeChild(__sr); } } else { const __sr = ${claim}; if (__sr && __sr.parentNode) __sr.parentNode.replaceChild(${v2}, __sr); } }`);
43747
44499
  if (regionBudget && ctx2.markerless)
43748
44500
  ctx2.push(`${regionBudget} = 0;`);
43749
44501
  };
@@ -43760,7 +44512,7 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
43760
44512
  const frag = ctx2.n();
43761
44513
  const wipeMount = ctx2.linkNames.has(node.componentName);
43762
44514
  const savedHydrate = ctx2.hydrate;
43763
- if (wipeMount)
44515
+ if (wipeMount || ctx2.selfClaimNames.has(node.componentName))
43764
44516
  ctx2.hydrate = false;
43765
44517
  ctx2.push(`const ${frag} = (() => { const $f = document.createDocumentFragment();`);
43766
44518
  const savedEffects = ctx2.effects;
@@ -43782,11 +44534,17 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
43782
44534
  }
43783
44535
  ctx2.push(`let ${v} = undefined;`);
43784
44536
  ctx2.push(`if (__hydrate) __hydrate.childFrame = (__hydrate.childFrame || 0) + 1;`);
43785
- ctx2.push(`try { ${v} = ${awaitKw}${access}(${callArgs()}, __registry, ${walkerArg}); } finally { if (__hydrate) __hydrate.childFrame--; }`);
44537
+ ctx2.push(`try { ${v} = toDomNode(${awaitKw}${access}(${callArgs()}, __registry, ${walkerArg})); } finally { if (__hydrate) __hydrate.childFrame--; }`);
44538
+ const rootsVar = trackedDeps.length > 0 ? ctx2.n() : null;
44539
+ if (rootsVar)
44540
+ ctx2.push(`const ${rootsVar} = ${v} && ${v}.nodeType === 11 ? Array.from(${v}.childNodes) : [${v}];`);
43786
44541
  if (ctx2.markerless && promptExpr && !plainTarget && regionBudget)
43787
44542
  ctx2.push(`${regionBudget} = 0;`);
43788
44543
  maybeReplace(v);
43789
44544
  maybeRetire();
44545
+ if (trackedDeps.length > 0) {
44546
+ ctx2.push(`rerenderNode(${rootsVar}, [${trackedDeps.join(", ")}], () => ${awaitKw}${access}(${callArgs()}, __registry, ${walkerArg}));`);
44547
+ }
43790
44548
  return v;
43791
44549
  } else {
43792
44550
  for (const slot of slotChildren) {
@@ -43810,12 +44568,18 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
43810
44568
  propsEntries.push(`children: ${frag}`);
43811
44569
  }
43812
44570
  if (calleeExpr) {
43813
- ctx2.push(`const ${v} = ${calleeExpr}(${callArgs()});`);
44571
+ ctx2.push(`const ${v} = toDomNode(${calleeExpr}(${callArgs()}));`);
43814
44572
  } else if (ctx2.importedNames.has(node.componentName)) {
43815
- ctx2.push(`const ${v} = ${awaitKw}${node.componentName}(${callArgs()});`);
44573
+ ctx2.push(`const ${v} = toDomNode(${awaitKw}${node.componentName}(${callArgs()}));`);
43816
44574
  } else {
43817
44575
  ctx2.push(`if (${compPrefix}[${JSON.stringify(node.componentName)}] == null) throw new Error(${JSON.stringify(`Component "${node.componentName}" was not found while rendering. Declare it with the \`component\` keyword, import it, or register it in the component registry.`)});`);
43818
- ctx2.push(`const ${v} = ${awaitKw}${compPrefix}[${JSON.stringify(node.componentName)}](${callArgs()});`);
44576
+ ctx2.push(`const ${v} = toDomNode(${awaitKw}${compPrefix}[${JSON.stringify(node.componentName)}](${callArgs()}));`);
44577
+ }
44578
+ if (trackedDeps.length > 0) {
44579
+ const calleeRef = calleeExpr ?? (ctx2.importedNames.has(node.componentName) ? node.componentName : `${compPrefix}[${JSON.stringify(node.componentName)}]`);
44580
+ const rootsVar2 = ctx2.n();
44581
+ ctx2.push(`const ${rootsVar2} = ${v} && ${v}.nodeType === 11 ? Array.from(${v}.childNodes) : [${v}];`);
44582
+ ctx2.push(`rerenderNode(${rootsVar2}, [${trackedDeps.join(", ")}], () => ${awaitKw}${calleeRef}(${callArgs()}));`);
43819
44583
  }
43820
44584
  }
43821
44585
  return v;
@@ -45055,7 +45819,7 @@ function emitClientFromIR2(ir, options) {
45055
45819
  }
45056
45820
  }
45057
45821
  const exportCode = exportLines.join("\n");
45058
- const runtimeNames = ["track", "get", "set", "destroy_block", "getActiveComponent", "setActiveComponent", "reactiveProps", "applyStyle"];
45822
+ const runtimeNames = ["track", "get", "set", "destroy_block", "getActiveComponent", "setActiveComponent", "reactiveProps", "applyStyle", "toDomNode", "rerenderNode"];
45059
45823
  if (ir.components.some((c) => !isStaticIR2(c.body)))
45060
45824
  runtimeNames.push("effect");
45061
45825
  for (const name of usedRuntimeBindings2(ir))
@@ -45123,12 +45887,16 @@ function compileClientBoth2(source, _componentName, sourcePath2, opts) {
45123
45887
  }
45124
45888
  const alloc = nameAllocFor2(sourcePath2);
45125
45889
  const comp = emitClientFromIR2(ir, { forceClient: true, nameAllocator: alloc });
45890
+ const aliases = vskRegistryAliases(ir.imports, ir.exportAliases);
45891
+ const reexportPaths = sourcePath2 ? collectVskReexportPaths(ir.reexportSources, sourcePath2) : [];
45126
45892
  if (opts?.skipHyd)
45127
- return { comp, hyd: "", name };
45893
+ return { comp, hyd: "", name, aliases, reexportPaths };
45128
45894
  return {
45129
45895
  comp,
45130
45896
  hyd: emitClientFromIR2(irHyd, { forceClient: true, hydrate: true, includeTopLevel: false, nameAllocator: alloc, markerless: opts?.markerless !== false }),
45131
- name
45897
+ name,
45898
+ aliases,
45899
+ reexportPaths
45132
45900
  };
45133
45901
  }
45134
45902
 
@@ -46449,6 +47217,35 @@ function extractCompiledNodes2(code, isTarget) {
46449
47217
  function isModuleLevel2(node) {
46450
47218
  return node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
46451
47219
  }
47220
+ function nativeLibraryImportStubs2(code) {
47221
+ let ast;
47222
+ try {
47223
+ ast = parse4(code);
47224
+ } catch {
47225
+ return "";
47226
+ }
47227
+ const body = ast.body ?? [];
47228
+ const bindings = [];
47229
+ for (const node of body) {
47230
+ if (node?.type !== "ImportDeclaration")
47231
+ continue;
47232
+ const src2 = node.source?.value;
47233
+ if (typeof src2 !== "string" || !src2.startsWith("@vesk/") || src2.startsWith("@vesk/runtime"))
47234
+ continue;
47235
+ for (const spec of node.specifiers ?? []) {
47236
+ if (typeof spec?.local?.name === "string")
47237
+ bindings.push([spec.local.name, src2]);
47238
+ }
47239
+ }
47240
+ if (bindings.length === 0)
47241
+ return "";
47242
+ const lines = bindings.map(([local, spec]) => {
47243
+ const message = `web preview: native library "${spec}" has no browser equivalent on the web (dev-only) \u2014 binding "${local}" cannot be provided in vesk dev --web. Build for Android to use it.`;
47244
+ const thrower = `throw Object.assign(new Error(${JSON.stringify(message)}), { __veskPreviewMissing: ${JSON.stringify(spec)} })`;
47245
+ return `const ${local} = new Proxy(function () {}, { get: function () { ${thrower}; }, apply: function () { ${thrower}; }, construct: function () { ${thrower}; } });`;
47246
+ });
47247
+ return lines.join("\n") + "\n\n";
47248
+ }
46452
47249
  function demoteExports2(code) {
46453
47250
  let ast;
46454
47251
  try {
@@ -46815,7 +47612,7 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options) {
46815
47612
  }
46816
47613
  const namesBefore = cache2 ? new Set(runtimeImportNames) : null;
46817
47614
  const importedPaths = resolveVskImports(filePath, (p, n) => compileFile2(p, n, output, imports));
46818
- const { comp: rawComp, hyd: rawHyd, name: actualName } = compileClientBoth(src2, null, filePath);
47615
+ const { comp: rawComp, hyd: rawHyd, name: actualName, aliases, reexportPaths } = compileClientBoth(src2, null, filePath);
46819
47616
  const compWithImports = rawComp ? stripExports(stripVskImports(stripRuntimeImport(rawComp))) : "";
46820
47617
  const hydWithImports = rawHyd ? stripExports(stripVskImports(stripRuntimeImport(rawHyd))) : "";
46821
47618
  const compSpecs = [];
@@ -46838,6 +47635,12 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options) {
46838
47635
  output.push(`Object.defineProperty(__components, ${JSON.stringify(resolvedName)}, { get: () => __components[${JSON.stringify(actualName)}], configurable: true });`);
46839
47636
  output.push(`Object.defineProperty(__hydrators, ${JSON.stringify(resolvedName)}, { get: () => __hydrators[${JSON.stringify(actualName)}], configurable: true });`);
46840
47637
  }
47638
+ for (const alias of aliases || []) {
47639
+ output.push(`Object.defineProperty(__components, ${JSON.stringify(alias.exported)}, { get: () => __components[${JSON.stringify(alias.local)}], configurable: true });`);
47640
+ output.push(`Object.defineProperty(__hydrators, ${JSON.stringify(alias.exported)}, { get: () => __hydrators[${JSON.stringify(alias.local)}], configurable: true });`);
47641
+ }
47642
+ for (const reexportPath of reexportPaths || [])
47643
+ compileFile2(reexportPath, null, output, imports);
46841
47644
  if (cache2 && namesBefore) {
46842
47645
  const st = statSync14(filePath);
46843
47646
  cache2.files.set(filePath, {
@@ -46981,7 +47784,7 @@ ${entry.code}
46981
47784
  const err = e;
46982
47785
  console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
46983
47786
  const stripped = demoteExports2(removeCompiledNodes2(entry.code, isAnyImport2));
46984
- finalCode = chunkIIFE(stripped);
47787
+ finalCode = chunkIIFE(nativeLibraryImportStubs2(entry.code) + stripped);
46985
47788
  } finally {
46986
47789
  try {
46987
47790
  rmSync4(tmpBase, { recursive: true, force: true });
@@ -46989,7 +47792,7 @@ ${entry.code}
46989
47792
  }
46990
47793
  }
46991
47794
  } else {
46992
- finalCode = chunkIIFE(entry.code);
47795
+ finalCode = chunkIIFE(demoteExports2(entry.code));
46993
47796
  }
46994
47797
  chunks.push({ name: entry.name, code: finalCode });
46995
47798
  }
@@ -47212,7 +48015,7 @@ function appendHmrGlobals2(code) {
47212
48015
  return code + "globalThis.__vesk_hmr_eval = (code, n) => {\n if (!n || n !== globalThis.__vesk_hmr_nonce) throw new Error('vesk hmr: invalid nonce');\n return eval(code);\n};\n";
47213
48016
  }
47214
48017
  async function buildMainBundle2(routeTree, runtimeDir, codeSplit, mono, hmr, importRuntime, runtimeImportNames, routeDataCache) {
47215
- const baseRuntimeImports = ["createFileRouter", "get", "set", "effect", "track", "destroy_block", "getActiveComponent", "setActiveComponent", "NavLink", "Link", "reactiveProps", "matchRoute", "ensureChunk"];
48018
+ const baseRuntimeImports = ["createFileRouter", "get", "set", "effect", "track", "destroy_block", "getActiveComponent", "setActiveComponent", "NavLink", "Link", "reactiveProps", "matchRoute", "ensureChunk", "toDomNode", "rerenderNode"];
47216
48019
  const allRuntimeImports = runtimeImportNames && runtimeImportNames.size > 0 ? [.../* @__PURE__ */ new Set([...baseRuntimeImports, ...runtimeImportNames])] : baseRuntimeImports;
47217
48020
  const runtimeGlobals = [
47218
48021
  "reconcile",
@@ -53212,11 +54015,11 @@ ${prettifyHtml(body)}
53212
54015
  </html>`;
53213
54016
  return applyHtmlPlugins(fullHtml, ctx2.plugins, { sourcePath: ctx2.url.pathname });
53214
54017
  }
53215
- const leaf = chain.find((n) => n.page);
53216
- if (!leaf) return null;
53217
- const src2 = readFileSync37(resolve37(ctx2.appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
53218
- const compName = resolveComponentName(src2) || leaf.page;
53219
- const html = await renderFullPage(src2, compName, { params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: actionCssUrls(ctx2.appDirPath), security: ctx2.security, sourcePath: resolve37(ctx2.appDirPath, leaf.sourceDir, "page.vsk"), plugins: ctx2.plugins });
54018
+ const leaf2 = chain.find((n) => n.page);
54019
+ if (!leaf2) return null;
54020
+ const src2 = readFileSync37(resolve37(ctx2.appDirPath, leaf2.sourceDir, "page.vsk"), "utf-8");
54021
+ const compName = resolveComponentName(src2) || leaf2.page;
54022
+ const html = await renderFullPage(src2, compName, { params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: actionCssUrls(ctx2.appDirPath), security: ctx2.security, sourcePath: resolve37(ctx2.appDirPath, leaf2.sourceDir, "page.vsk"), plugins: ctx2.plugins });
53220
54023
  return applyHtmlPlugins(html.replace("</body>", ' <script type="module" src="/_vesk/hmr.js"></script>\n</body>'), ctx2.plugins, { sourcePath: ctx2.url.pathname });
53221
54024
  }
53222
54025
  async function handleActionRequest(req, res, ctx2) {
@@ -54673,11 +55476,11 @@ ${prettifyHtml(body)}
54673
55476
  html = injectDevScripts(html);
54674
55477
  html = await applyHtmlPlugins(html, getActiveDevPlugins(), { sourcePath: url.pathname });
54675
55478
  } else {
54676
- const leaf = chain.find((n) => n.page);
54677
- if (leaf) {
54678
- const src2 = readFileSync38(resolve38(appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
54679
- const compName = extractCompName2(src2) || leaf.page;
54680
- html = await renderFullPage(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve38(appDirPath, leaf.sourceDir, "page.vsk"), cached: cachedSsrCompile(ssrCompileCache, src2, resolve38(appDirPath, leaf.sourceDir, "page.vsk")), plugins: getActiveDevPlugins() });
55479
+ const leaf2 = chain.find((n) => n.page);
55480
+ if (leaf2) {
55481
+ const src2 = readFileSync38(resolve38(appDirPath, leaf2.sourceDir, "page.vsk"), "utf-8");
55482
+ const compName = extractCompName2(src2) || leaf2.page;
55483
+ html = await renderFullPage(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve38(appDirPath, leaf2.sourceDir, "page.vsk"), cached: cachedSsrCompile(ssrCompileCache, src2, resolve38(appDirPath, leaf2.sourceDir, "page.vsk")), plugins: getActiveDevPlugins() });
54681
55484
  html = html.replace("</body>", ' <script type="module" src="/_vesk/hmr.js"></script>\n</body>');
54682
55485
  html = await applyHtmlPlugins(html, getActiveDevPlugins(), { sourcePath: url.pathname });
54683
55486
  } else {
@@ -54703,11 +55506,11 @@ ${prettifyHtml(body)}
54703
55506
  const chain = cleanChain;
54704
55507
  const hasLayout = chain.some((n) => n.layout && existsSync42(resolve38(appDirPath, n.sourceDir, "layout.vsk")));
54705
55508
  if (!hasLayout) {
54706
- const leaf = chain.find((n) => n.page);
54707
- if (leaf) {
54708
- const src2 = readFileSync38(resolve38(appDirPath, leaf.sourceDir, "page.vsk"), "utf-8");
54709
- const compName = extractCompName2(src2) || leaf.page;
54710
- yield* renderPageStream(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve38(appDirPath, leaf.sourceDir, "page.vsk"), cached: cachedSsrCompile(ssrCompileCache, src2, resolve38(appDirPath, leaf.sourceDir, "page.vsk")), plugins: getActiveDevPlugins() });
55509
+ const leaf2 = chain.find((n) => n.page);
55510
+ if (leaf2) {
55511
+ const src2 = readFileSync38(resolve38(appDirPath, leaf2.sourceDir, "page.vsk"), "utf-8");
55512
+ const compName = extractCompName2(src2) || leaf2.page;
55513
+ yield* renderPageStream(src2, compName, { params: matched.params }, /* @__PURE__ */ new Map(), { hydrate: true, clientScriptUrl: "/_vesk/client.js", cssUrls: activeCssUrls(), security, externalDataScript: storeDataScript, sourcePath: resolve38(appDirPath, leaf2.sourceDir, "page.vsk"), cached: cachedSsrCompile(ssrCompileCache, src2, resolve38(appDirPath, leaf2.sourceDir, "page.vsk")), plugins: getActiveDevPlugins() });
54711
55514
  } else {
54712
55515
  throw new Error("No page or layout matched");
54713
55516
  }
@@ -55162,11 +55965,15 @@ __export(index_server_exports2, {
55162
55965
  get_server_context: () => get_server_context,
55163
55966
  headers: () => headers,
55164
55967
  isFormAction: () => isFormAction,
55968
+ isLeaf: () => isLeaf,
55165
55969
  isLoadingActive: () => isLoadingActive,
55970
+ isPrimitive: () => isPrimitive,
55971
+ isVeskComponent: () => isVeskComponent,
55166
55972
  is_destroyed: () => is_destroyed,
55167
55973
  isr: () => isr,
55168
55974
  isrConfigToRevalidate: () => isrConfigToRevalidate,
55169
55975
  issuesToFieldMap: () => issuesToFieldMap,
55976
+ leaf: () => leaf,
55170
55977
  locals: () => locals,
55171
55978
  maxLength: () => maxLength,
55172
55979
  minLength: () => minLength,
@@ -55180,12 +55987,14 @@ __export(index_server_exports2, {
55180
55987
  permanentRedirect: () => permanentRedirect,
55181
55988
  pop_component: () => pop_component,
55182
55989
  pre_effect: () => pre_effect,
55990
+ primitive: () => primitive,
55183
55991
  push_component: () => push_component,
55184
55992
  readSignedCookie: () => readSignedCookie2,
55185
55993
  redirect: () => redirect,
55186
55994
  removeHook: () => removeHook,
55187
55995
  render: () => render,
55188
55996
  required: () => required,
55997
+ rerenderNode: () => rerenderNode,
55189
55998
  resolveSsrResources: () => resolveSsrResources,
55190
55999
  resume_block: () => resume_block,
55191
56000
  revalidateComponent: () => revalidateComponent,
@@ -55209,6 +56018,7 @@ __export(index_server_exports2, {
55209
56018
  set_server_context: () => set_server_context,
55210
56019
  signCookie: () => signCookie2,
55211
56020
  tick: () => tick,
56021
+ toDomNode: () => toDomNode,
55212
56022
  track: () => track,
55213
56023
  unlink_block: () => unlink_block,
55214
56024
  unsignCookie: () => unsignCookie2,
@@ -55244,6 +56054,7 @@ init_experiment();
55244
56054
  init_form();
55245
56055
  init_md();
55246
56056
  init_headless();
56057
+ init_primitive();
55247
56058
  init_loading_indicator();
55248
56059
  init_action();
55249
56060