@vesk/vesk-cli 0.2.50 → 0.2.51

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 +820 -84
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -199,6 +199,42 @@ var init_errors = __esm({
199
199
  * - `value` — `ns.max` read as a value. Component tags resolve; plain value
200
200
  * reads do not, because nothing binds `ns` at runtime.
201
201
  */
202
+ /**
203
+ * An imported `.ts`/`.js` module could not be parsed.
204
+ *
205
+ * This used to be silent, and that is the whole point of the diagnostic. A
206
+ * parse failure meant the module's RAW, untranspiled source was substituted,
207
+ * so TypeScript syntax reached `new Function` and the module blew up much
208
+ * later with a bare `Unexpected token ':'` — attributed to no file, at a
209
+ * point in the build far from the code that caused it. It also poisoned the
210
+ * whole shared module graph: one unparseable module left its exports
211
+ * undefined, so unrelated consumers failed with `X is not iterable`.
212
+ *
213
+ * Two real constructs hit this: a parameter annotation that survived the
214
+ * stripper only when the parameter also had a default value, and a generic
215
+ * arrow's type parameter list, which the JSX tokenizer cannot read at all.
216
+ * Both are fixed; this error exists so the NEXT such gap is reported at the
217
+ * right file with the right line instead of surfacing three modules later.
218
+ */
219
+ static moduleParseFailed(context = {}) {
220
+ return new _VeskError(
221
+ `Could not parse an imported module${context.reason ? `: ${context.reason}` : "."}`,
222
+ {
223
+ ...context,
224
+ code: context.code || "V0901",
225
+ suggestions: [
226
+ "Check the line the ^ marker points at \u2014 it is the construct the parser stopped on.",
227
+ "If it is TypeScript syntax the stripper does not handle, simplifying it here fixes every module that imports this file.",
228
+ "This is a bug in the compiler, not in your code, if the construct is ordinary TypeScript \u2014 please report it with the source line."
229
+ ],
230
+ nextSteps: [
231
+ "A module that fails to parse is substituted with its raw source, so every type annotation it contains becomes a runtime SyntaxError.",
232
+ "The failure is reported here, at the offending file and line, rather than as an `Unexpected token` in whichever module happened to import it."
233
+ ],
234
+ tip: "Ordinary TypeScript should parse; if this fires on valid TS, the parser is missing a construct."
235
+ }
236
+ );
237
+ }
202
238
  static vskNamespaceMember(context = {}) {
203
239
  const nested = context.form === "nested";
204
240
  return new _VeskError(
@@ -3569,7 +3605,13 @@ function flattenLayoutChain(tree, pathParts, result = []) {
3569
3605
  for (let i = 0; i < tree.length; i++) {
3570
3606
  const node = tree[i];
3571
3607
  if (node.isGroup) {
3608
+ const before = result.length;
3572
3609
  flattenLayoutChain(node.children || [], pathParts, result);
3610
+ if (result.length > before) continue;
3611
+ if (node.page && (pathParts.length === 0 || pathParts.every((p) => p === ""))) {
3612
+ result.push(node);
3613
+ break;
3614
+ }
3573
3615
  continue;
3574
3616
  }
3575
3617
  const part = pathParts[0];
@@ -3591,6 +3633,11 @@ function flattenLayoutChain(tree, pathParts, result = []) {
3591
3633
  if (node.standalone) result.length = 0;
3592
3634
  result.push(node);
3593
3635
  if (isLeaf2) {
3636
+ if (!node.page && (node.children || []).length > 0) {
3637
+ const before = result.length;
3638
+ flattenLayoutChain(node.children || [], remaining, result);
3639
+ if (result.length > before) break;
3640
+ }
3594
3641
  break;
3595
3642
  } else if ((node.children || []).length > 0) {
3596
3643
  flattenLayoutChain(node.children || [], remaining, result);
@@ -18773,6 +18820,162 @@ function preprocessForClauses(source) {
18773
18820
  }
18774
18821
  return { code: chars.join(""), annotations };
18775
18822
  }
18823
+ function blankGenericArrowTypeParams(source) {
18824
+ let changed = false;
18825
+ const chars = source.split("");
18826
+ let i = 0;
18827
+ const isSpace = (ch) => isSpaceChar(ch);
18828
+ while (i < source.length) {
18829
+ const ch = source[i];
18830
+ if (ch === '"' || ch === "'" || ch === "`") {
18831
+ const quote = ch;
18832
+ let j2 = i + 1;
18833
+ while (j2 < source.length) {
18834
+ if (source[j2] === "\\") {
18835
+ j2 += 2;
18836
+ continue;
18837
+ }
18838
+ if (source[j2] === quote) {
18839
+ j2++;
18840
+ break;
18841
+ }
18842
+ if (quote === "`" && source[j2] === "$" && source[j2 + 1] === "{") {
18843
+ let depth = 1;
18844
+ j2 += 2;
18845
+ while (j2 < source.length && depth > 0) {
18846
+ if (source[j2] === "{") depth++;
18847
+ else if (source[j2] === "}") depth--;
18848
+ j2++;
18849
+ }
18850
+ continue;
18851
+ }
18852
+ j2++;
18853
+ }
18854
+ i = j2;
18855
+ continue;
18856
+ }
18857
+ if (ch === "/" && source[i + 1] === "/") {
18858
+ while (i < source.length && source[i] !== "\n") i++;
18859
+ continue;
18860
+ }
18861
+ if (ch === "/" && source[i + 1] === "*") {
18862
+ i += 2;
18863
+ while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) i++;
18864
+ i += 2;
18865
+ continue;
18866
+ }
18867
+ if (ch !== "<") {
18868
+ i++;
18869
+ continue;
18870
+ }
18871
+ let j = i + 1;
18872
+ let angle = 1;
18873
+ let end = -1;
18874
+ let bail = false;
18875
+ while (j < source.length) {
18876
+ const c = source[j];
18877
+ if (c === "<") {
18878
+ angle++;
18879
+ j++;
18880
+ continue;
18881
+ }
18882
+ if (c === ">") {
18883
+ angle--;
18884
+ j++;
18885
+ if (angle === 0) {
18886
+ end = j;
18887
+ break;
18888
+ }
18889
+ continue;
18890
+ }
18891
+ if (c === "(" || c === "[" || c === "{") {
18892
+ const close = c === "(" ? ")" : c === "[" ? "]" : "}";
18893
+ let depth = 0;
18894
+ while (j < source.length) {
18895
+ const d = source[j];
18896
+ if (d === c) depth++;
18897
+ else if (d === close) {
18898
+ depth--;
18899
+ if (depth === 0) {
18900
+ j++;
18901
+ break;
18902
+ }
18903
+ }
18904
+ j++;
18905
+ }
18906
+ continue;
18907
+ }
18908
+ if (c === ";" || c === "\n") {
18909
+ bail = true;
18910
+ break;
18911
+ }
18912
+ j++;
18913
+ }
18914
+ if (bail || end < 0) {
18915
+ i++;
18916
+ continue;
18917
+ }
18918
+ if (!isArrowParameterList(source, end)) {
18919
+ i = end;
18920
+ continue;
18921
+ }
18922
+ for (let p = i; p < end; p++) {
18923
+ if (chars[p] !== "\n") chars[p] = " ";
18924
+ }
18925
+ changed = true;
18926
+ i = end;
18927
+ }
18928
+ return changed ? chars.join("") : source;
18929
+ }
18930
+ function isArrowParameterList(source, from) {
18931
+ let i = from;
18932
+ while (i < source.length && isSpaceChar(source[i])) i++;
18933
+ if (source[i] !== "(") return false;
18934
+ let depth = 0;
18935
+ while (i < source.length) {
18936
+ const ch = source[i];
18937
+ if (ch === "(" || ch === "[" || ch === "{") {
18938
+ depth++;
18939
+ i++;
18940
+ continue;
18941
+ }
18942
+ if (ch === ")" || ch === "]" || ch === "}") {
18943
+ depth--;
18944
+ i++;
18945
+ if (depth === 0) break;
18946
+ continue;
18947
+ }
18948
+ i++;
18949
+ }
18950
+ if (depth !== 0) return false;
18951
+ while (i < source.length && isSpaceChar(source[i])) i++;
18952
+ if (source[i] === ":") {
18953
+ i++;
18954
+ let tdepth = 0;
18955
+ while (i < source.length) {
18956
+ const ch = source[i];
18957
+ if (ch === "(" || ch === "[" || ch === "{") {
18958
+ tdepth++;
18959
+ i++;
18960
+ continue;
18961
+ }
18962
+ if (ch === ")" || ch === "]" || ch === "}") {
18963
+ if (tdepth === 0) return false;
18964
+ tdepth--;
18965
+ i++;
18966
+ continue;
18967
+ }
18968
+ if (tdepth === 0 && ch === "=" && source[i + 1] === ">") return true;
18969
+ if (tdepth === 0 && (ch === ";" || ch === "\n")) return false;
18970
+ i++;
18971
+ }
18972
+ return false;
18973
+ }
18974
+ return source[i] === "=" && source[i + 1] === ">";
18975
+ }
18976
+ function isSpaceChar(ch) {
18977
+ return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f" || ch === "\v";
18978
+ }
18776
18979
  function createBaseParser() {
18777
18980
  return Parser.extend(tsPlugin({}), VeskParserPlugin());
18778
18981
  }
@@ -18785,7 +18988,7 @@ function parseGeneratedJs(source) {
18785
18988
  }
18786
18989
  function parse4(source, options = {}) {
18787
18990
  const ParserClass = createBaseParser();
18788
- const { code, annotations } = preprocessForClauses(blankComments(source));
18991
+ const { code, annotations } = preprocessForClauses(blankGenericArrowTypeParams(blankComments(source)));
18789
18992
  const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
18790
18993
  const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
18791
18994
  let parseable = code;
@@ -18987,13 +19190,33 @@ function stripTsTypes(ast) {
18987
19190
  }
18988
19191
  });
18989
19192
  }
19193
+ function stripParamTypes(p) {
19194
+ if (!p) return;
19195
+ if (p.typeAnnotation) p.typeAnnotation = null;
19196
+ if (p.optional) p.optional = false;
19197
+ switch (p.type) {
19198
+ case "AssignmentPattern":
19199
+ stripParamTypes(p.left);
19200
+ break;
19201
+ case "RestElement":
19202
+ stripParamTypes(p.argument);
19203
+ break;
19204
+ case "ObjectPattern":
19205
+ for (const prop of p.properties || []) {
19206
+ stripParamTypes(prop.value || prop.argument || prop);
19207
+ }
19208
+ break;
19209
+ case "ArrayPattern":
19210
+ for (const el of p.elements || []) if (el) stripParamTypes(el);
19211
+ break;
19212
+ default:
19213
+ break;
19214
+ }
19215
+ }
18990
19216
  function stripFunctionTypes(node) {
18991
19217
  if (node.returnType) node.returnType = null;
18992
19218
  if (node.typeParameters) node.typeParameters = null;
18993
- for (const p of node.params || []) {
18994
- if (p.typeAnnotation) p.typeAnnotation = null;
18995
- if (p.optional) p.optional = false;
18996
- }
19219
+ for (const p of node.params || []) stripParamTypes(p);
18997
19220
  }
18998
19221
  function stripCodeTypes(code) {
18999
19222
  let ast;
@@ -19171,6 +19394,7 @@ function loadSsrModule(absPath) {
19171
19394
  }
19172
19395
  } else {
19173
19396
  const src2 = readSsrSource(absPath);
19397
+ if (src2?.parseError) throw src2.parseError;
19174
19398
  const body = src2?.ast?.body || [];
19175
19399
  if (src2 && isPureReexportBarrel(body)) {
19176
19400
  exportsObj = createLazyBarrelExports(buildBarrelSpec(body), dirname2(absPath));
@@ -19247,13 +19471,19 @@ function readSsrSource(absPath) {
19247
19471
  return null;
19248
19472
  }
19249
19473
  const raw2 = cachedRaw;
19250
- let ast = null;
19251
19474
  try {
19252
- ast = parse4(raw2, { filename: absPath });
19253
- } catch {
19254
- ast = null;
19475
+ return { raw: raw2, ast: parse4(raw2, { filename: absPath }) };
19476
+ } catch (e) {
19477
+ const err = e;
19478
+ let parseError;
19479
+ if (err instanceof VeskError) {
19480
+ parseError = err;
19481
+ if (err.code === void 0) err.code = "V0901";
19482
+ } else {
19483
+ parseError = VeskError.moduleParseFailed({ file: absPath, reason: e?.message });
19484
+ }
19485
+ return { raw: raw2, ast: null, parseError };
19255
19486
  }
19256
- return { raw: raw2, ast };
19257
19487
  }
19258
19488
  function isPureReexportBarrel(body) {
19259
19489
  for (const stmt of body) {
@@ -19319,7 +19549,7 @@ function createLazyBarrelExports(spec, dir) {
19319
19549
  const loadSource = (source) => {
19320
19550
  let target = targets.get(source);
19321
19551
  if (!target) {
19322
- target = resolveSsrModule(source, dir) ?? "";
19552
+ target = (isCompilerOwnedTarget(source) ? resolveCompilerOwnedModule(source) : resolveSsrModule(source, dir)) ?? "";
19323
19553
  if (!target) return null;
19324
19554
  targets.set(source, target);
19325
19555
  }
@@ -19404,6 +19634,7 @@ function evaluateModuleFile(absPath, exportsObj, src2) {
19404
19634
  let ast;
19405
19635
  if (src2) {
19406
19636
  ast = src2.ast;
19637
+ if (!ast && src2.parseError) throw src2.parseError;
19407
19638
  } else {
19408
19639
  try {
19409
19640
  ast = parse4(raw2, { filename: absPath });
@@ -19477,8 +19708,25 @@ function scanUnsupportedNode(node, inFunction = false) {
19477
19708
  }
19478
19709
  return null;
19479
19710
  }
19711
+ function resolveCompilerOwnedModule(specifier) {
19712
+ const viaExports = resolveViaPackageExports(specifier, process.cwd());
19713
+ if (viaExports) return viaExports;
19714
+ const viaModuleField = resolveViaPackageModuleField(specifier, process.cwd());
19715
+ if (viaModuleField) return viaModuleField;
19716
+ const native = nativeResolve(specifier, process.cwd());
19717
+ if (native && !isBuiltinPath(native)) return native;
19718
+ return null;
19719
+ }
19480
19720
  function createModuleRequire(fromDir) {
19481
19721
  return (specifier) => {
19722
+ if (isCompilerOwnedTarget(specifier)) {
19723
+ const resolved2 = resolveCompilerOwnedModule(specifier);
19724
+ if (resolved2) {
19725
+ const native = nativeRequireFallback(resolved2);
19726
+ if (native) return native;
19727
+ }
19728
+ throw new Error(`Cannot load module '${specifier}'`);
19729
+ }
19482
19730
  const resolved = resolveSsrModule(specifier, fromDir);
19483
19731
  if (!resolved) throw new Error(`Cannot find module '${specifier}'`);
19484
19732
  for (const frame of depStack) frame.add(resolved);
@@ -20026,6 +20274,7 @@ function collectModuleBundled(absPath, collector) {
20026
20274
  } else {
20027
20275
  const src2 = readSsrSource(absPath);
20028
20276
  if (!src2 || !src2.ast) {
20277
+ if (src2?.parseError) throw src2.parseError;
20029
20278
  const raw2 = src2 ? src2.raw : "// unreadable during build\nmodule.exports = {};";
20030
20279
  collector.modules.push({ key, code: raw2, dir, deps: {} });
20031
20280
  return key;
@@ -20072,6 +20321,7 @@ var init_module_imports = __esm({
20072
20321
  init_parser();
20073
20322
  init_strip_ts();
20074
20323
  init_tokens();
20324
+ init_errors();
20075
20325
  RUNTIME_PREFIXES = ["@vesk/runtime/", "@vesk/reactivity/", "@vesk/types", "@vesk/"];
20076
20326
  EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs", ".jsx", ".json"];
20077
20327
  BUILTIN_PREFIX = "\0builtin:";
@@ -20541,6 +20791,22 @@ function jsxTagDepth(nameNode) {
20541
20791
  }
20542
20792
  return depth;
20543
20793
  }
20794
+ function unwrapHelperBody(node) {
20795
+ let body = node;
20796
+ if (body?.type === "ArrowFunctionExpression" || body?.type === "FunctionExpression") body = body.body;
20797
+ if (body?.type === "BlockStatement") {
20798
+ const stmts = (body.body || []).filter((s) => s.type !== "EmptyStatement");
20799
+ if (stmts.length !== 1) return null;
20800
+ body = stmts[0];
20801
+ }
20802
+ if (body?.type === "ReturnStatement") body = body.argument;
20803
+ if (!body) return null;
20804
+ if (body.type !== "CallExpression") return null;
20805
+ if (body.callee?.type !== "Identifier") return null;
20806
+ const args2 = body.arguments || [];
20807
+ if (args2.length === 0 || args2[0]?.type !== "ObjectExpression") return null;
20808
+ return body;
20809
+ }
20544
20810
  function collectVskNamespaceLocals(ast) {
20545
20811
  const namespaceLocals = /* @__PURE__ */ new Map();
20546
20812
  for (const node of ast.body || []) {
@@ -20574,6 +20840,34 @@ function markShadowedBindings(node, namespaceLocals) {
20574
20840
  markShadowedBindings(node[key], namespaceLocals);
20575
20841
  }
20576
20842
  }
20843
+ function collectFileValueBindings(ast) {
20844
+ const names = /* @__PURE__ */ new Set();
20845
+ for (const node of ast.body || []) {
20846
+ if (node.type === "ComponentDeclaration") continue;
20847
+ if (node.type === "ImportDeclaration") continue;
20848
+ const target = node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" ? node.declaration : node;
20849
+ if (!target) continue;
20850
+ if (target.type === "VariableDeclaration") {
20851
+ for (const d of target.declarations || []) for (const n of declaredBindingNames(d)) names.add(n);
20852
+ continue;
20853
+ }
20854
+ for (const n of declaredBindingNames(target)) names.add(n);
20855
+ }
20856
+ return names;
20857
+ }
20858
+ function collectComponentValueNames(compNode) {
20859
+ const names = /* @__PURE__ */ new Set();
20860
+ if (!compNode) return names;
20861
+ for (const p of compNode.params || []) for (const n of declaredBindingNames(p)) names.add(n);
20862
+ for (const stmt of compNode.body?.body || []) {
20863
+ if (stmt.type === "VariableDeclaration") {
20864
+ for (const d of stmt.declarations || []) for (const n of declaredBindingNames(d)) names.add(n);
20865
+ continue;
20866
+ }
20867
+ for (const n of declaredBindingNames(stmt)) names.add(n);
20868
+ }
20869
+ return names;
20870
+ }
20577
20871
  function declaredBindingNames(node) {
20578
20872
  const out = [];
20579
20873
  const pushPattern = (id) => {
@@ -20643,9 +20937,149 @@ function findNamespaceValueUse(node, locals2) {
20643
20937
  }
20644
20938
  return null;
20645
20939
  }
20940
+ function collectComponentCallHelpers(source, ast) {
20941
+ const out = /* @__PURE__ */ new Map();
20942
+ for (const node of ast.body || []) {
20943
+ const decl = node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" ? node.declaration : node;
20944
+ if (!decl) continue;
20945
+ let name = null;
20946
+ let fn = null;
20947
+ if (decl.type === "VariableDeclaration" && decl.declarations?.length === 1) {
20948
+ const d = decl.declarations[0];
20949
+ if (d.id?.type === "Identifier") {
20950
+ name = d.id.name;
20951
+ fn = d.init;
20952
+ }
20953
+ } else if (decl.type === "FunctionDeclaration" && decl.id?.name) {
20954
+ name = decl.id.name;
20955
+ fn = decl;
20956
+ }
20957
+ if (!name || !fn) continue;
20958
+ if (fn.type !== "ArrowFunctionExpression" && fn.type !== "FunctionExpression" && fn.type !== "FunctionDeclaration") continue;
20959
+ const params = fn.params || [];
20960
+ if (params.some((p) => p.type !== "Identifier")) continue;
20961
+ const body = unwrapHelperBody(fn);
20962
+ if (body === null) continue;
20963
+ const args2 = body.arguments || [];
20964
+ const propsObj = args2[0];
20965
+ const props = [];
20966
+ const spreadProps = [];
20967
+ const slots = [];
20968
+ for (const prop of propsObj.properties || []) {
20969
+ if (prop.type === "SpreadElement") {
20970
+ spreadProps.push(prop.argument);
20971
+ continue;
20972
+ }
20973
+ const pname = prop.key.type === "Identifier" ? prop.key.name : prop.key.value;
20974
+ if (prop.value.type === "JSXElement" || prop.value.type === "JSXFragment") {
20975
+ slots.push({ name: pname, nodes: exprToIR(source, prop.value) });
20976
+ continue;
20977
+ }
20978
+ props.push({ name: pname, value: prop.value });
20979
+ }
20980
+ const paramNames = params.map((p) => p.name);
20981
+ out.set(name, { props, spreadProps, slots, paramNames, componentName: body.callee.name });
20982
+ }
20983
+ return out;
20984
+ }
20985
+ function substituteHelperParams(node, bindings) {
20986
+ if (!node || typeof node !== "object") return node;
20987
+ if (Array.isArray(node)) {
20988
+ const out2 = [];
20989
+ for (const child of node) {
20990
+ const next = substituteHelperParams(child, bindings);
20991
+ if (next === null) return null;
20992
+ out2.push(next);
20993
+ }
20994
+ return out2;
20995
+ }
20996
+ if (typeof node.type !== "string") return node;
20997
+ if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") return null;
20998
+ if (node.type === "Identifier" && bindings.has(node.name)) {
20999
+ const bound = bindings.get(node.name);
21000
+ return bound === null ? null : bound;
21001
+ }
21002
+ const out = {};
21003
+ for (const key of Object.keys(node)) {
21004
+ if (key === "loc" || key === "range" || key === "start" || key === "end") {
21005
+ out[key] = node[key];
21006
+ continue;
21007
+ }
21008
+ const next = substituteHelperParams(node[key], bindings);
21009
+ if (next === null) return null;
21010
+ out[key] = next;
21011
+ }
21012
+ return out;
21013
+ }
21014
+ function helperCallToIR(source, helper, args2) {
21015
+ const compName = helper.componentName;
21016
+ const bindings = /* @__PURE__ */ new Map();
21017
+ helper.paramNames.forEach((param, i) => bindings.set(param, args2[i] ?? null));
21018
+ for (const bound of bindings.values()) if (bound === null) return null;
21019
+ const props = [];
21020
+ for (const p of helper.props) {
21021
+ const substituted = substituteHelperParams(p.value, bindings);
21022
+ if (substituted === null) return null;
21023
+ props.push({ name: p.name, value: toExpression(source, substituted) });
21024
+ }
21025
+ const spreadProps = [];
21026
+ for (const sp of helper.spreadProps) {
21027
+ const substituted = substituteHelperParams(sp, bindings);
21028
+ if (substituted === null) return null;
21029
+ spreadProps.push(toExpression(source, substituted));
21030
+ }
21031
+ return [new ComponentCall(compName, props, helper.slots.flatMap((s) => [new PropSlot(s.name, s.nodes)]), spreadProps, -1, componentValueCallee(compName))];
21032
+ }
20646
21033
  function isHTMLTag(name) {
20647
21034
  return name.length > 0 && name[0] === name[0].toLowerCase();
20648
21035
  }
21036
+ function componentValueCallee(tagName) {
21037
+ if (!currentComponentValues || !currentComponentValues.has(tagName)) return null;
21038
+ return tagName;
21039
+ }
21040
+ function componentCallInExpression(expr) {
21041
+ if (!expr || expr.type !== "CallExpression") return null;
21042
+ const callee = expr.callee;
21043
+ if (!callee || callee.type !== "Identifier") return null;
21044
+ if (!isComponentValueName(callee.name)) return null;
21045
+ const args2 = expr.arguments || [];
21046
+ if (args2.length === 0 || !args2[0] || args2[0].type !== "ObjectExpression") return null;
21047
+ return expr;
21048
+ }
21049
+ function isComponentValueName(name) {
21050
+ if (currentFileComponentNames?.has(name)) return true;
21051
+ if (currentComponentValues?.has(name)) return true;
21052
+ return currentFileValueBindings?.has(name) || currentImportedNames?.has(name) || false;
21053
+ }
21054
+ function componentCallToIR(source, expr) {
21055
+ const calleeName = expr.callee.name;
21056
+ const args2 = expr.arguments || [];
21057
+ const propsArg = args2[0];
21058
+ const props = [];
21059
+ const spreadProps = [];
21060
+ const slots = [];
21061
+ for (const prop of propsArg.properties || []) {
21062
+ if (prop.type === "SpreadElement") {
21063
+ spreadProps.push(toExpression(source, prop.argument));
21064
+ continue;
21065
+ }
21066
+ const name = prop.key.type === "Identifier" ? prop.key.name : prop.key.value;
21067
+ if (prop.value.type === "JSXElement" || prop.value.type === "JSXFragment") {
21068
+ slots.push(new PropSlot(name, exprToIR(source, prop.value)));
21069
+ continue;
21070
+ }
21071
+ props.push({ name, value: toExpression(source, prop.value) });
21072
+ }
21073
+ const children = args2.length > 1 ? [new RuntimeStatement(`/* [vesk] extra arguments to a component call are ignored */ ${getSource(source, args2[1])}`)] : [];
21074
+ return [new ComponentCall(
21075
+ calleeName,
21076
+ props,
21077
+ [...children, ...slots],
21078
+ spreadProps,
21079
+ expr.start ?? -1,
21080
+ componentValueCallee(calleeName)
21081
+ )];
21082
+ }
20649
21083
  function isMapCall(expr) {
20650
21084
  return expr.type === "CallExpression" && expr.callee.type === "MemberExpression" && expr.callee.property.name === "map" && expr.arguments.length === 1 && expr.arguments[0].type === "ArrowFunctionExpression";
20651
21085
  }
@@ -20914,7 +21348,7 @@ function processJSXChildren(source, children) {
20914
21348
  continue;
20915
21349
  }
20916
21350
  }
20917
- result.push(new DynamicBinding(toExpression(source, expr)));
21351
+ result.push(...exprToIR(source, expr));
20918
21352
  i++;
20919
21353
  } else if (child.type === "JSXElement") {
20920
21354
  result.push(...processJSXElement(source, child));
@@ -20960,6 +21394,12 @@ function exprToIR(source, expr) {
20960
21394
  return [new MapRegion(arrayExpr, itemVar, bodyNodes, keyExpr, indexVar)];
20961
21395
  }
20962
21396
  if (expr.type === "ParenthesizedExpression") return exprToIR(source, expr.expression);
21397
+ if (componentCallInExpression(expr) !== null) return componentCallToIR(source, expr);
21398
+ if (expr?.type === "CallExpression" && currentComponentCallHelpers?.has(expr.callee?.name)) {
21399
+ const helper = currentComponentCallHelpers.get(expr.callee.name);
21400
+ const inlined = helperCallToIR(source, helper, expr.arguments || []);
21401
+ if (inlined !== null) return inlined;
21402
+ }
20963
21403
  if (expr.type === "ConditionalExpression") {
20964
21404
  const condExpr = toExpression(source, expr.test);
20965
21405
  const consequent = exprToIR(source, expr.consequent);
@@ -21027,12 +21467,12 @@ function processJSXElement(source, element) {
21027
21467
  }
21028
21468
  if (!isHTMLTag(tagName) && selfClosing) {
21029
21469
  const { props, spreadProps, slots } = extractProps(source, element);
21030
- return [new ComponentCall(tagName, props, slots.map((s) => new PropSlot(s.name, s.nodes)), spreadProps, element.start)];
21470
+ return [new ComponentCall(tagName, props, slots.map((s) => new PropSlot(s.name, s.nodes)), spreadProps, element.start, componentValueCallee(tagName))];
21031
21471
  }
21032
21472
  if (!isHTMLTag(tagName)) {
21033
21473
  const { props, spreadProps, slots } = extractProps(source, element);
21034
21474
  const children2 = processJSXChildren(source, element.children || []);
21035
- return [new ComponentCall(tagName, props, [...children2, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start)];
21475
+ return [new ComponentCall(tagName, props, [...children2, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start, componentValueCallee(tagName))];
21036
21476
  }
21037
21477
  const attributes = element.openingElement.attributes.filter((attr) => attr.type !== "JSXSpreadAttribute").map((attr) => processAttribute(source, attr));
21038
21478
  const staticAttrs = [];
@@ -21445,6 +21885,17 @@ function generateIR(ast, source, filename) {
21445
21885
  const vskNamespaceLocals = collectVskNamespaceLocals(ast);
21446
21886
  const prevNamespaceLocals = currentVskNamespaceLocals;
21447
21887
  const prevSourceFile = currentSourceFile;
21888
+ const fileValueBindings = collectFileValueBindings(ast);
21889
+ currentComponentCallHelpers = collectComponentCallHelpers(source, ast);
21890
+ const prevFileComponentNames = currentFileComponentNames;
21891
+ const prevFileValueBindings = currentFileValueBindings;
21892
+ const prevImportedNames = currentImportedNames;
21893
+ const fileComponentNames = new Set(
21894
+ (ast.body || []).map((n) => n.type === "ExportNamedDeclaration" || n.type === "ExportDefaultDeclaration" ? n.declaration : n).filter((n) => n?.type === "ComponentDeclaration").map((n) => n.id.name)
21895
+ );
21896
+ currentFileComponentNames = fileComponentNames;
21897
+ currentFileValueBindings = fileValueBindings;
21898
+ currentImportedNames = importedNames;
21448
21899
  currentVskNamespaceLocals = vskNamespaceLocals;
21449
21900
  currentSourceFile = file;
21450
21901
  try {
@@ -21550,61 +22001,68 @@ function generateIR(ast, source, filename) {
21550
22001
  }
21551
22002
  const name = inner.id.name;
21552
22003
  const paramNames = getParamNames(inner.params, source);
21553
- const firstParam = inner.params?.[0];
21554
- const propsAlias = firstParam && firstParam.type === "Identifier" ? firstParam.name : null;
21555
- const propsType = getPropsType(inner.params, source);
21556
- const bodyStmts = inner.body.body;
21557
- const isClientComp = !!inner.client;
21558
- const prevSlotProps = __slotProps;
21559
- __slotProps = slotPropNamesFromType(propsType);
21560
- __propsParam = propsAlias || null;
21561
- if (isStatementMode(bodyStmts)) {
21562
- const raw2 = processStatementModeBody(source, bodyStmts, file);
21563
- const { body, css } = extractStyle(raw2);
21564
- validateBlocks(name, isClientComp, body, file, source);
21565
- const comp = new ComponentIR(name, paramNames, body, { mode: "statement", exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
21566
- comp.style = css;
21567
- components.push(comp);
21568
- __slotProps = prevSlotProps;
21569
- } else {
21570
- const guardClauses = [];
21571
- let mainReturn = null;
21572
- const preamble = [];
21573
- for (const stmt of bodyStmts) {
21574
- if (stmt.type === "VeskBlock") {
21575
- const innerBody = processStatementModeBody(source, stmt.body, file);
21576
- if (stmt.tag === "server") {
21577
- preamble.push(new ServerBlock(innerBody));
21578
- } else if (stmt.tag === "client") {
21579
- preamble.push(new ClientBlock(innerBody));
21580
- }
21581
- } else if (stmt.type === "ReturnStatement") {
21582
- mainReturn = stmt;
21583
- } else if (isTrackDeclaration(stmt)) {
21584
- const elements = stmt.declarations[0].id.elements;
21585
- const trackName = elements[0]?.name;
21586
- const rawName = elements.length > 1 ? elements[1]?.name : null;
21587
- const init = getSource(source, stmt.declarations[0].init);
21588
- if (trackName) preamble.push(new TrackDecl(trackName, init, rawName));
21589
- const refName = getComponentRefName(stmt);
21590
- if (refName) preamble.push(new ComponentRef(refName));
21591
- } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
21592
- guardClauses.push(stmt);
21593
- } else if (stmt.type === "ClassDeclaration") {
21594
- const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
21595
- throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
21596
- } else {
21597
- const raw2 = getSource(source, stmt);
21598
- if (raw2) preamble.push(new RuntimeStatement(raw2, stmt, source));
22004
+ const valueNames = collectComponentValueNames(inner);
22005
+ const prevComponentValues = currentComponentValues;
22006
+ currentComponentValues = new Set([...valueNames].filter((n) => !fileComponentNames.has(n)));
22007
+ try {
22008
+ const firstParam = inner.params?.[0];
22009
+ const propsAlias = firstParam && firstParam.type === "Identifier" ? firstParam.name : null;
22010
+ const propsType = getPropsType(inner.params, source);
22011
+ const bodyStmts = inner.body.body;
22012
+ const isClientComp = !!inner.client;
22013
+ const prevSlotProps = __slotProps;
22014
+ __slotProps = slotPropNamesFromType(propsType);
22015
+ __propsParam = propsAlias || null;
22016
+ if (isStatementMode(bodyStmts)) {
22017
+ const raw2 = processStatementModeBody(source, bodyStmts, file);
22018
+ const { body, css } = extractStyle(raw2);
22019
+ validateBlocks(name, isClientComp, body, file, source);
22020
+ const comp = new ComponentIR(name, paramNames, body, { mode: "statement", exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
22021
+ comp.style = css;
22022
+ components.push(comp);
22023
+ __slotProps = prevSlotProps;
22024
+ } else {
22025
+ const guardClauses = [];
22026
+ let mainReturn = null;
22027
+ const preamble = [];
22028
+ for (const stmt of bodyStmts) {
22029
+ if (stmt.type === "VeskBlock") {
22030
+ const innerBody = processStatementModeBody(source, stmt.body, file);
22031
+ if (stmt.tag === "server") {
22032
+ preamble.push(new ServerBlock(innerBody));
22033
+ } else if (stmt.tag === "client") {
22034
+ preamble.push(new ClientBlock(innerBody));
22035
+ }
22036
+ } else if (stmt.type === "ReturnStatement") {
22037
+ mainReturn = stmt;
22038
+ } else if (isTrackDeclaration(stmt)) {
22039
+ const elements = stmt.declarations[0].id.elements;
22040
+ const trackName = elements[0]?.name;
22041
+ const rawName = elements.length > 1 ? elements[1]?.name : null;
22042
+ const init = getSource(source, stmt.declarations[0].init);
22043
+ if (trackName) preamble.push(new TrackDecl(trackName, init, rawName));
22044
+ const refName = getComponentRefName(stmt);
22045
+ if (refName) preamble.push(new ComponentRef(refName));
22046
+ } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
22047
+ guardClauses.push(stmt);
22048
+ } else if (stmt.type === "ClassDeclaration") {
22049
+ const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
22050
+ throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
22051
+ } else {
22052
+ const raw2 = getSource(source, stmt);
22053
+ if (raw2) preamble.push(new RuntimeStatement(raw2, stmt, source));
22054
+ }
21599
22055
  }
22056
+ const guardBody = buildGuardChain(source, guardClauses, mainReturn);
22057
+ const { body, css } = extractStyle([...preamble, ...guardBody]);
22058
+ validateBlocks(name, isClientComp, body, file, source);
22059
+ const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
22060
+ comp.style = css;
22061
+ components.push(comp);
22062
+ __slotProps = prevSlotProps;
21600
22063
  }
21601
- const guardBody = buildGuardChain(source, guardClauses, mainReturn);
21602
- const { body, css } = extractStyle([...preamble, ...guardBody]);
21603
- validateBlocks(name, isClientComp, body, file, source);
21604
- const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType, propsAlias });
21605
- comp.style = css;
21606
- components.push(comp);
21607
- __slotProps = prevSlotProps;
22064
+ } finally {
22065
+ currentComponentValues = prevComponentValues;
21608
22066
  }
21609
22067
  }
21610
22068
  const asyncNames = new Set(components.filter((c) => c.isAsync || c.ssrAwait).map((c) => c.name));
@@ -21701,9 +22159,13 @@ function generateIR(ast, source, filename) {
21701
22159
  } finally {
21702
22160
  currentVskNamespaceLocals = prevNamespaceLocals;
21703
22161
  currentSourceFile = prevSourceFile;
22162
+ currentFileComponentNames = prevFileComponentNames;
22163
+ currentFileValueBindings = prevFileValueBindings;
22164
+ currentImportedNames = prevImportedNames;
22165
+ currentComponentCallHelpers = null;
21704
22166
  }
21705
22167
  }
21706
- var __vskAnnotations, __slotProps, __propsParam, currentVskNamespaceLocals, currentSourceFile;
22168
+ var __vskAnnotations, __slotProps, __propsParam, currentVskNamespaceLocals, currentSourceFile, currentComponentValues, currentFileComponentNames, currentFileValueBindings, currentImportedNames, currentComponentCallHelpers;
21707
22169
  var init_ir_generator = __esm({
21708
22170
  "../compiler/src/ir-generator.ts"() {
21709
22171
  "use strict";
@@ -21719,6 +22181,11 @@ var init_ir_generator = __esm({
21719
22181
  __slotProps = null;
21720
22182
  __propsParam = null;
21721
22183
  currentVskNamespaceLocals = null;
22184
+ currentComponentValues = null;
22185
+ currentFileComponentNames = null;
22186
+ currentFileValueBindings = null;
22187
+ currentImportedNames = null;
22188
+ currentComponentCallHelpers = null;
21722
22189
  }
21723
22190
  });
21724
22191
 
@@ -21727,6 +22194,7 @@ var server_utils_exports = {};
21727
22194
  __export(server_utils_exports, {
21728
22195
  CorsResponse: () => CorsResponse,
21729
22196
  DEFAULT_MAX_BODY_BYTES: () => DEFAULT_MAX_BODY_BYTES,
22197
+ VOID_ELEMENTS: () => VOID_ELEMENTS2,
21730
22198
  __vskForceClaim: () => __vskForceClaim,
21731
22199
  __vskHydrate: () => __vskHydrate,
21732
22200
  __vskId: () => __vskId,
@@ -32203,7 +32671,7 @@ function componentMarker(compName) {
32203
32671
  }
32204
32672
  function irNodeToJS(node, importedNames, isAsync = false, tracked2) {
32205
32673
  importedNames = importedNames || __vskImportedNames;
32206
- if (node instanceof StaticNode) return staticNodeToJS(node, isAsync, tracked2);
32674
+ if (node instanceof StaticNode) return staticNodeToJS(node, isAsync, tracked2, __inForeignContent);
32207
32675
  if (node instanceof TextNode) {
32208
32676
  if (!node.value) return "";
32209
32677
  return `__out.push(${JSON.stringify(escapeHtml(node.value))});`;
@@ -32281,7 +32749,7 @@ function exprJSX(node, tracked2) {
32281
32749
  }
32282
32750
  return exprJS(transformTracked({ ...node, ast: lowered }, tracked2 || /* @__PURE__ */ new Map()));
32283
32751
  }
32284
- function staticNodeToJS(node, isAsync = false, tracked2) {
32752
+ function staticNodeToJS(node, isAsync = false, tracked2, inForeign = false) {
32285
32753
  const lines = [];
32286
32754
  const dynAttrTargets = /* @__PURE__ */ new Set();
32287
32755
  for (const child of node.children) {
@@ -32307,17 +32775,19 @@ function staticNodeToJS(node, isAsync = false, tracked2) {
32307
32775
  }
32308
32776
  }
32309
32777
  if (node.selfClosing) {
32310
- let tag = openTag + " />";
32778
+ const voidOrForeign = VOID_ELEMENTS2.has(node.tag) || inForeign;
32779
+ const tail = voidOrForeign ? " />" : `></${node.tag}>`;
32311
32780
  if (hasDynamicAttrs) {
32312
- let expr = JSON.stringify(tag);
32781
+ let expr = JSON.stringify(openTag);
32313
32782
  for (const child of node.children) {
32314
32783
  if (child instanceof DynamicBinding && child.kind === "attribute" && child.target !== "ref" && !isEvent(child.target)) {
32315
32784
  expr += ` + __attr(${JSON.stringify(child.target)}, ${exprJSX(child.expression, tracked2)})`;
32316
32785
  }
32317
32786
  }
32787
+ expr += ` + ${JSON.stringify(tail)}`;
32318
32788
  lines.push(`__out.push(${expr});`);
32319
32789
  } else {
32320
- lines.push(`__out.push(${JSON.stringify(tag)});`);
32790
+ lines.push(`__out.push(${JSON.stringify(openTag + tail)});`);
32321
32791
  }
32322
32792
  return lines.join("\n");
32323
32793
  }
@@ -32336,10 +32806,13 @@ function staticNodeToJS(node, isAsync = false, tracked2) {
32336
32806
  } else {
32337
32807
  lines.push(`__out.push(${JSON.stringify(openTag + ">")});`);
32338
32808
  }
32809
+ const prevForeign = __inForeignContent;
32810
+ if (FOREIGN_ROOTS.has(node.tag)) __inForeignContent = true;
32339
32811
  for (const child of childNodes) {
32340
32812
  const code = irNodeToJS(child, null, isAsync, tracked2);
32341
32813
  if (code) lines.push(code);
32342
32814
  }
32815
+ __inForeignContent = prevForeign;
32343
32816
  lines.push(`__out.push(${JSON.stringify("</" + node.tag + ">")});`);
32344
32817
  return lines.join("\n");
32345
32818
  }
@@ -32736,7 +33209,7 @@ ${entry.source}
32736
33209
  }
32737
33210
  return map;
32738
33211
  }
32739
- var __currentCompName;
33212
+ var __currentCompName, __inForeignContent, FOREIGN_ROOTS;
32740
33213
  var init_server_jsgen = __esm({
32741
33214
  "../compiler/src/server-jsgen.ts"() {
32742
33215
  "use strict";
@@ -32748,6 +33221,8 @@ var init_server_jsgen = __esm({
32748
33221
  init_server_jsx_lowering();
32749
33222
  init_vsk_imports();
32750
33223
  __currentCompName = "";
33224
+ __inForeignContent = false;
33225
+ FOREIGN_ROOTS = /* @__PURE__ */ new Set(["svg", "math"]);
32751
33226
  }
32752
33227
  });
32753
33228
 
@@ -38733,6 +39208,39 @@ var init_errors2 = __esm({
38733
39208
  * - `value` — `ns.max` read as a value. Component tags resolve; plain value
38734
39209
  * reads do not, because nothing binds `ns` at runtime.
38735
39210
  */
39211
+ /**
39212
+ * An imported `.ts`/`.js` module could not be parsed.
39213
+ *
39214
+ * This used to be silent, and that is the whole point of the diagnostic. A
39215
+ * parse failure meant the module's RAW, untranspiled source was substituted,
39216
+ * so TypeScript syntax reached `new Function` and the module blew up much
39217
+ * later with a bare `Unexpected token ':'` — attributed to no file, at a
39218
+ * point in the build far from the code that caused it. It also poisoned the
39219
+ * whole shared module graph: one unparseable module left its exports
39220
+ * undefined, so unrelated consumers failed with `X is not iterable`.
39221
+ *
39222
+ * Two real constructs hit this: a parameter annotation that survived the
39223
+ * stripper only when the parameter also had a default value, and a generic
39224
+ * arrow's type parameter list, which the JSX tokenizer cannot read at all.
39225
+ * Both are fixed; this error exists so the NEXT such gap is reported at the
39226
+ * right file with the right line instead of surfacing three modules later.
39227
+ */
39228
+ static moduleParseFailed(context = {}) {
39229
+ return new _VeskError(`Could not parse an imported module${context.reason ? `: ${context.reason}` : "."}`, {
39230
+ ...context,
39231
+ code: context.code || "V0901",
39232
+ suggestions: [
39233
+ "Check the line the ^ marker points at \u2014 it is the construct the parser stopped on.",
39234
+ "If it is TypeScript syntax the stripper does not handle, simplifying it here fixes every module that imports this file.",
39235
+ "This is a bug in the compiler, not in your code, if the construct is ordinary TypeScript \u2014 please report it with the source line."
39236
+ ],
39237
+ nextSteps: [
39238
+ "A module that fails to parse is substituted with its raw source, so every type annotation it contains becomes a runtime SyntaxError.",
39239
+ "The failure is reported here, at the offending file and line, rather than as an `Unexpected token` in whichever module happened to import it."
39240
+ ],
39241
+ tip: "Ordinary TypeScript should parse; if this fires on valid TS, the parser is missing a construct."
39242
+ });
39243
+ }
38736
39244
  static vskNamespaceMember(context = {}) {
38737
39245
  const nested = context.form === "nested";
38738
39246
  return new _VeskError(nested ? "A `.vsk` namespace is flat, so `<ns.Sub.Icon />` cannot be resolved." : "A `.vsk` namespace resolves component tags only, so `ns.value` is not available.", {
@@ -46239,12 +46747,182 @@ function preprocessForClauses2(source) {
46239
46747
  }
46240
46748
  return { code: chars.join(""), annotations };
46241
46749
  }
46750
+ function blankGenericArrowTypeParams2(source) {
46751
+ let changed = false;
46752
+ const chars = source.split("");
46753
+ let i = 0;
46754
+ const isSpace = (ch) => isSpaceChar2(ch);
46755
+ while (i < source.length) {
46756
+ const ch = source[i];
46757
+ if (ch === '"' || ch === "'" || ch === "`") {
46758
+ const quote = ch;
46759
+ let j2 = i + 1;
46760
+ while (j2 < source.length) {
46761
+ if (source[j2] === "\\") {
46762
+ j2 += 2;
46763
+ continue;
46764
+ }
46765
+ if (source[j2] === quote) {
46766
+ j2++;
46767
+ break;
46768
+ }
46769
+ if (quote === "`" && source[j2] === "$" && source[j2 + 1] === "{") {
46770
+ let depth = 1;
46771
+ j2 += 2;
46772
+ while (j2 < source.length && depth > 0) {
46773
+ if (source[j2] === "{")
46774
+ depth++;
46775
+ else if (source[j2] === "}")
46776
+ depth--;
46777
+ j2++;
46778
+ }
46779
+ continue;
46780
+ }
46781
+ j2++;
46782
+ }
46783
+ i = j2;
46784
+ continue;
46785
+ }
46786
+ if (ch === "/" && source[i + 1] === "/") {
46787
+ while (i < source.length && source[i] !== "\n")
46788
+ i++;
46789
+ continue;
46790
+ }
46791
+ if (ch === "/" && source[i + 1] === "*") {
46792
+ i += 2;
46793
+ while (i < source.length && !(source[i] === "*" && source[i + 1] === "/"))
46794
+ i++;
46795
+ i += 2;
46796
+ continue;
46797
+ }
46798
+ if (ch !== "<") {
46799
+ i++;
46800
+ continue;
46801
+ }
46802
+ let j = i + 1;
46803
+ let angle = 1;
46804
+ let end = -1;
46805
+ let bail = false;
46806
+ while (j < source.length) {
46807
+ const c = source[j];
46808
+ if (c === "<") {
46809
+ angle++;
46810
+ j++;
46811
+ continue;
46812
+ }
46813
+ if (c === ">") {
46814
+ angle--;
46815
+ j++;
46816
+ if (angle === 0) {
46817
+ end = j;
46818
+ break;
46819
+ }
46820
+ continue;
46821
+ }
46822
+ if (c === "(" || c === "[" || c === "{") {
46823
+ const close = c === "(" ? ")" : c === "[" ? "]" : "}";
46824
+ let depth = 0;
46825
+ while (j < source.length) {
46826
+ const d = source[j];
46827
+ if (d === c)
46828
+ depth++;
46829
+ else if (d === close) {
46830
+ depth--;
46831
+ if (depth === 0) {
46832
+ j++;
46833
+ break;
46834
+ }
46835
+ }
46836
+ j++;
46837
+ }
46838
+ continue;
46839
+ }
46840
+ if (c === ";" || c === "\n") {
46841
+ bail = true;
46842
+ break;
46843
+ }
46844
+ j++;
46845
+ }
46846
+ if (bail || end < 0) {
46847
+ i++;
46848
+ continue;
46849
+ }
46850
+ if (!isArrowParameterList2(source, end)) {
46851
+ i = end;
46852
+ continue;
46853
+ }
46854
+ for (let p = i; p < end; p++) {
46855
+ if (chars[p] !== "\n")
46856
+ chars[p] = " ";
46857
+ }
46858
+ changed = true;
46859
+ i = end;
46860
+ }
46861
+ return changed ? chars.join("") : source;
46862
+ }
46863
+ function isArrowParameterList2(source, from) {
46864
+ let i = from;
46865
+ while (i < source.length && isSpaceChar2(source[i]))
46866
+ i++;
46867
+ if (source[i] !== "(")
46868
+ return false;
46869
+ let depth = 0;
46870
+ while (i < source.length) {
46871
+ const ch = source[i];
46872
+ if (ch === "(" || ch === "[" || ch === "{") {
46873
+ depth++;
46874
+ i++;
46875
+ continue;
46876
+ }
46877
+ if (ch === ")" || ch === "]" || ch === "}") {
46878
+ depth--;
46879
+ i++;
46880
+ if (depth === 0)
46881
+ break;
46882
+ continue;
46883
+ }
46884
+ i++;
46885
+ }
46886
+ if (depth !== 0)
46887
+ return false;
46888
+ while (i < source.length && isSpaceChar2(source[i]))
46889
+ i++;
46890
+ if (source[i] === ":") {
46891
+ i++;
46892
+ let tdepth = 0;
46893
+ while (i < source.length) {
46894
+ const ch = source[i];
46895
+ if (ch === "(" || ch === "[" || ch === "{") {
46896
+ tdepth++;
46897
+ i++;
46898
+ continue;
46899
+ }
46900
+ if (ch === ")" || ch === "]" || ch === "}") {
46901
+ if (tdepth === 0)
46902
+ return false;
46903
+ tdepth--;
46904
+ i++;
46905
+ continue;
46906
+ }
46907
+ if (tdepth === 0 && ch === "=" && source[i + 1] === ">")
46908
+ return true;
46909
+ if (tdepth === 0 && (ch === ";" || ch === "\n"))
46910
+ return false;
46911
+ i++;
46912
+ }
46913
+ return false;
46914
+ }
46915
+ return source[i] === "=" && source[i + 1] === ">";
46916
+ }
46917
+ function isSpaceChar2(ch) {
46918
+ return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f" || ch === "\v";
46919
+ }
46242
46920
  function createBaseParser2() {
46243
46921
  return Parser.extend(tsPlugin2({}), VeskParserPlugin());
46244
46922
  }
46245
46923
  function parse5(source, options = {}) {
46246
46924
  const ParserClass = createBaseParser2();
46247
- const { code, annotations } = preprocessForClauses2(blankComments(source));
46925
+ const { code, annotations } = preprocessForClauses2(blankGenericArrowTypeParams2(blankComments(source)));
46248
46926
  const vskSource = !options.filename || String(options.filename).endsWith(".vsk");
46249
46927
  const specifierExports = vskSource ? findSpecifierExports(code).filter((e) => !hasTopLevelValueDeclaration(code, e.local)) : [];
46250
46928
  let parseable = code;
@@ -49189,12 +49867,26 @@ ${entry.code}
49189
49867
  write: false,
49190
49868
  logLevel: "silent",
49191
49869
  loader: { ".js": "tsx" },
49870
+ // Bundled dependencies (lucide-vesk above all) carry a license
49871
+ // banner per module, and a barrel import pulls in hundreds of
49872
+ // them. Those banners were ~339 KB of a 350 KB chunk, which is
49873
+ // what kept a barrel import from being usable at all. Attribution
49874
+ // for a dependency stays in its own package; shipping every
49875
+ // module's header inside our own chunk adds nothing.
49876
+ legalComments: "none",
49192
49877
  ...appTsconfig ? { tsconfig: appTsconfig } : {}
49193
49878
  });
49194
49879
  finalCode = result.outputFiles[0].text;
49195
49880
  } catch (e) {
49196
49881
  const err = e;
49197
- console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
49882
+ const detail = err?.errors?.map((x) => {
49883
+ const at2 = x.location?.file ? ` (${x.location.file}${x.location.line ? `:${x.location.line}` : ""})` : "";
49884
+ return x.text + at2;
49885
+ }).join(" | ") || err?.message || String(e);
49886
+ console.error("[vesk] chunk bundle failed", entry.name, detail);
49887
+ if (options?.strict) {
49888
+ throw new Error(`[vesk] chunk bundle failed: ${entry.name} \u2014 ${detail}`);
49889
+ }
49198
49890
  const stripped = demoteExports(removeCompiledNodes(entry.code, isAnyImport));
49199
49891
  finalCode = chunkIIFE(nativeLibraryImportStubs(entry.code) + stripped);
49200
49892
  } finally {
@@ -50378,6 +51070,8 @@ async function build2(appDir, options) {
50378
51070
  bundleOpts.codeSplit = true;
50379
51071
  if (options?.hmr)
50380
51072
  bundleOpts.hmr = true;
51073
+ if (options?.strict)
51074
+ bundleOpts.strict = true;
50381
51075
  if (options?.routeDataCache !== void 0)
50382
51076
  bundleOpts.routeDataCache = options.routeDataCache;
50383
51077
  if (pluginsPipelines.length > 0)
@@ -50756,17 +51450,41 @@ function stripTsTypes2(ast) {
50756
51450
  }
50757
51451
  });
50758
51452
  }
51453
+ function stripParamTypes2(p) {
51454
+ if (!p)
51455
+ return;
51456
+ if (p.typeAnnotation)
51457
+ p.typeAnnotation = null;
51458
+ if (p.optional)
51459
+ p.optional = false;
51460
+ switch (p.type) {
51461
+ case "AssignmentPattern":
51462
+ stripParamTypes2(p.left);
51463
+ break;
51464
+ case "RestElement":
51465
+ stripParamTypes2(p.argument);
51466
+ break;
51467
+ case "ObjectPattern":
51468
+ for (const prop of p.properties || []) {
51469
+ stripParamTypes2(prop.value || prop.argument || prop);
51470
+ }
51471
+ break;
51472
+ case "ArrayPattern":
51473
+ for (const el of p.elements || [])
51474
+ if (el)
51475
+ stripParamTypes2(el);
51476
+ break;
51477
+ default:
51478
+ break;
51479
+ }
51480
+ }
50759
51481
  function stripFunctionTypes2(node) {
50760
51482
  if (node.returnType)
50761
51483
  node.returnType = null;
50762
51484
  if (node.typeParameters)
50763
51485
  node.typeParameters = null;
50764
- for (const p of node.params || []) {
50765
- if (p.typeAnnotation)
50766
- p.typeAnnotation = null;
50767
- if (p.optional)
50768
- p.optional = false;
50769
- }
51486
+ for (const p of node.params || [])
51487
+ stripParamTypes2(p);
50770
51488
  }
50771
51489
  function stripCodeTypes2(code) {
50772
51490
  let ast;
@@ -53546,6 +54264,10 @@ function matchUrl(tree, pathname) {
53546
54264
  pushWithStandalone(node);
53547
54265
  return true;
53548
54266
  }
54267
+ if (partIndex >= parts.length && node.page && node.fullPath === "/" + parts.join("/")) {
54268
+ pushWithStandalone(node);
54269
+ return true;
54270
+ }
53549
54271
  continue;
53550
54272
  }
53551
54273
  if (node.fullPath === "/") {
@@ -55115,12 +55837,26 @@ ${entry.code}
55115
55837
  write: false,
55116
55838
  logLevel: "silent",
55117
55839
  loader: { ".js": "tsx" },
55840
+ // Bundled dependencies (lucide-vesk above all) carry a license
55841
+ // banner per module, and a barrel import pulls in hundreds of
55842
+ // them. Those banners were ~339 KB of a 350 KB chunk, which is
55843
+ // what kept a barrel import from being usable at all. Attribution
55844
+ // for a dependency stays in its own package; shipping every
55845
+ // module's header inside our own chunk adds nothing.
55846
+ legalComments: "none",
55118
55847
  ...appTsconfig ? { tsconfig: appTsconfig } : {}
55119
55848
  });
55120
55849
  finalCode = result.outputFiles[0].text;
55121
55850
  } catch (e) {
55122
55851
  const err = e;
55123
- console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
55852
+ const detail = err?.errors?.map((x) => {
55853
+ const at2 = x.location?.file ? ` (${x.location.file}${x.location.line ? `:${x.location.line}` : ""})` : "";
55854
+ return x.text + at2;
55855
+ }).join(" | ") || err?.message || String(e);
55856
+ console.error("[vesk] chunk bundle failed", entry.name, detail);
55857
+ if (options?.strict) {
55858
+ throw new Error(`[vesk] chunk bundle failed: ${entry.name} \u2014 ${detail}`);
55859
+ }
55124
55860
  const stripped = demoteExports2(removeCompiledNodes2(entry.code, isAnyImport2));
55125
55861
  finalCode = chunkIIFE(nativeLibraryImportStubs2(entry.code) + stripped);
55126
55862
  } finally {
@@ -63558,7 +64294,7 @@ if (cmd === "build") {
63558
64294
  const config = rawConfig;
63559
64295
  const plugins = config.plugins || [];
63560
64296
  const mdCfg = config.md;
63561
- const opts = { outDir, publicDir, plugins, seo, strictSeo: strict, codeSplit: !restArgs.includes("--skip-split"), target };
64297
+ const opts = { outDir, publicDir, plugins, seo, strictSeo: strict, strict, codeSplit: !restArgs.includes("--skip-split"), target };
63562
64298
  if (mdCfg) opts.md = mdCfg;
63563
64299
  if (config.routeDataCache !== void 0) opts.routeDataCache = config.routeDataCache;
63564
64300
  if (platform) opts.platform = platform;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/vesk-cli",
3
- "version": "0.2.50",
3
+ "version": "0.2.51",
4
4
  "type": "module",
5
5
  "description": "Vesk — compiler-first framework for the post-VDOM web. vesk dev, vesk build.",
6
6
  "bin": {
@@ -8,10 +8,10 @@
8
8
  },
9
9
  "main": "./dist/cli.js",
10
10
  "dependencies": {
11
- "@vesk/adapter": "^0.2.50",
12
- "@vesk/compiler": "^0.2.50",
13
- "@vesk/plugin-tailwind": "^0.2.50",
14
- "@vesk/runtime": "^0.2.50",
11
+ "@vesk/adapter": "^0.2.51",
12
+ "@vesk/compiler": "^0.2.51",
13
+ "@vesk/plugin-tailwind": "^0.2.51",
14
+ "@vesk/runtime": "^0.2.51",
15
15
  "esrap": "^2.3.0",
16
16
  "typescript": "^5.8.0",
17
17
  "ws": "^8.18.0",