@vesk/compiler 0.2.25 → 0.2.27

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.
package/dist/errors.d.ts CHANGED
@@ -28,6 +28,9 @@ export declare class VeskError extends Error {
28
28
  static componentNotFound(name: string, available?: string[], context?: VeskErrorOptions): VeskError;
29
29
  static configError(msg: string, validOptions?: string[], context?: VeskErrorOptions): VeskError;
30
30
  static asyncChildInSyncParent(parentName: string, childName: string, context?: VeskErrorOptions): VeskError;
31
+ static attrJsxElement(context?: VeskErrorOptions & {
32
+ attr?: string;
33
+ }): VeskError;
31
34
  toString(): string;
32
35
  toJSON(): Record<string, unknown>;
33
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBxD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,WAAW,GAAE,MAAU,GAAG,MAAM,GAAG,IAAI,CAWrG;AAqCD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,EAAE,KAAK,SAAI,GAAG,MAAM,CAkBrG;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAgBD,qBAAa,SAAU,SAAQ,KAAK;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEF,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB;IAYxD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IA6BnG,MAAM,CAAC,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAmB3D,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAkBvF,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAkBvF,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAO3G,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAWvG,MAAM,CAAC,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAkB/G,QAAQ,IAAI,MAAM;IA0BlB,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAclC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBxD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,WAAW,GAAE,MAAU,GAAG,MAAM,GAAG,IAAI,CAWrG;AAqCD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,EAAE,KAAK,SAAI,GAAG,MAAM,CAkBrG;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAgBD,qBAAa,SAAU,SAAQ,KAAK;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEF,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB;IAYxD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IA8BnG,MAAM,CAAC,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAoB3D,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAmBvF,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAmBvF,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAO3G,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,MAAM,EAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAYvG,MAAM,CAAC,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS;IAmB/G,MAAM,CAAC,cAAc,CAAC,OAAO,GAAE,gBAAgB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,SAAS;IAmBpF,QAAQ,IAAI,MAAM;IA0BlB,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAclC"}
package/dist/errors.js CHANGED
@@ -142,6 +142,7 @@ export class VeskError extends Error {
142
142
  }
143
143
  return new VeskError(msg, {
144
144
  ...context,
145
+ code: context.code || 'V0401',
145
146
  suggestions: [name, ...allCandidates.slice(0, 8)],
146
147
  nextSteps,
147
148
  tip: isBuiltin
@@ -152,6 +153,7 @@ export class VeskError extends Error {
152
153
  static classDecl(context = {}) {
153
154
  return new VeskError('class declarations are not supported inside Vesk components.', {
154
155
  ...context,
156
+ code: context.code || 'V0402',
155
157
  suggestions: [
156
158
  'Use a plain object: const obj = { ... };',
157
159
  'Use a factory function: function create() { return { ... }; }',
@@ -167,6 +169,7 @@ export class VeskError extends Error {
167
169
  static serverBlockInClient(compName, context = {}) {
168
170
  return new VeskError(`{#server} block found in client island "${compName}". Client islands render on both server and client, so {#server} blocks have no effect.`, {
169
171
  ...context,
172
+ code: context.code || 'V0403',
170
173
  suggestions: [
171
174
  `Remove the {#server} block from "${compName}".`,
172
175
  `Or remove the \`client\` keyword from "${compName}" declaration.`,
@@ -181,6 +184,7 @@ export class VeskError extends Error {
181
184
  static clientBlockInServer(compName, context = {}) {
182
185
  return new VeskError(`{#client} block found in component "${compName}", but this component is not a client island. {#client} blocks are only allowed inside components declared with the \`client\` keyword.`, {
183
186
  ...context,
187
+ code: context.code || 'V0404',
184
188
  suggestions: [
185
189
  `Add \`client\`: \`component ${compName} client { ... }\``,
186
190
  `Or remove the {#client}...{/client} block.`,
@@ -201,6 +205,7 @@ export class VeskError extends Error {
201
205
  static configError(msg, validOptions = [], context = {}) {
202
206
  return new VeskError(msg, {
203
207
  ...context,
208
+ code: context.code || 'V0405',
204
209
  suggestions: validOptions.length ? [`Valid options: ${validOptions.join(', ')}`] : [],
205
210
  nextSteps: [
206
211
  'Check your vesk.config file for typos.',
@@ -211,6 +216,7 @@ export class VeskError extends Error {
211
216
  static asyncChildInSyncParent(parentName, childName, context = {}) {
212
217
  return new VeskError(`Component "${parentName}" renders "<${childName} />", but "<${childName} />" is async and "${parentName}" is not declared async.`, {
213
218
  ...context,
219
+ code: context.code || 'V0406',
214
220
  suggestions: [
215
221
  `Declare the parent async: \`async component ${parentName} ...\``,
216
222
  ],
@@ -222,8 +228,23 @@ export class VeskError extends Error {
222
228
  tip: `A component that renders an async component must itself be async so the renderer can await it before serializing the HTML. Async components also include components that call \`useFetch\`.`,
223
229
  });
224
230
  }
231
+ static attrJsxElement(context = {}) {
232
+ return new VeskError(`Attribute "${context.attr ?? ''}" on an HTML element is given a JSX element value. DOM attributes hold plain values — JSX elements belong to content or to a component prop (where they become a content slot).`, {
233
+ ...context,
234
+ code: context.code || 'V0407',
235
+ suggestions: [
236
+ 'Pass the element as a child instead: <div>{ <yourElement /> }</div>',
237
+ 'If the component accepts it, pass the element as a component prop instead of an HTML attribute.',
238
+ ],
239
+ nextSteps: [
240
+ 'Move the JSX element into the element\'s content so it renders as a child node.',
241
+ 'Component props can hold JSX elements — they are threaded as content slots and read back with {props.<name>}.',
242
+ ],
243
+ tip: 'JSX elements are content. They render inside an element or travel as a component prop — never as an attribute value on an HTML tag.',
244
+ });
245
+ }
225
246
  toString() {
226
- let out = `[vesk] ${this.message}`;
247
+ let out = this.code ? `[vesk ${this.code}] ${this.message}` : `[vesk] ${this.message}`;
227
248
  if (this.file) {
228
249
  out += `\n File: ${this.file}`;
229
250
  if (this.line) {
@@ -1 +1 @@
1
- {"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAoBP,MAAM,uBAAuB,CAAC;AA0L/B,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCnL;AAg0BD,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CA2Q9E"}
1
+ {"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAsBP,MAAM,uBAAuB,CAAC;AA8N/B,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCnL;AA07BD,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAoR9E"}
@@ -1,4 +1,4 @@
1
- import { IRRoot, ComponentIR, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, RuntimeStatement, ForLoop, TrackDecl, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, Expression, SlotNode, } from '@vesk/compiler/src/ir';
1
+ import { IRRoot, ComponentIR, StaticNode, TextNode, DynamicBinding, OpaqueDynamicRegion, MapRegion, WhileLoop, SwitchBlock, TryCatch, RuntimeStatement, ForLoop, TrackDecl, ComponentRef, ComponentCall, ServerBlock, ClientBlock, HeadBlock, Expression, SlotNode, PropSlot, PropSlotRender, } from '@vesk/compiler/src/ir';
2
2
  import { VeskError, codeFrame } from '@vesk/compiler/src/errors';
3
3
  import { createBaseParser } from '@vesk/compiler/src/parser';
4
4
  import { skipWhitespace, findBalancedEnd, splitTopLevel, startsWithIdentifier, stripDeclKeyword, isWhitespaceChar, collapseNewlineWhitespace } from '@vesk/compiler/src/scan';
@@ -7,6 +7,14 @@ import { stripTypeImport } from '@vesk/compiler/src/vsk-imports';
7
7
  import { importBindingPairs } from '@vesk/compiler/src/module-imports';
8
8
  import { collectCalledIdentifiers, extractImportNames, importModuleTarget } from '@vesk/compiler/src/tokens';
9
9
  let __vskAnnotations = [];
10
+ /**
11
+ * Prop names of the component currently being processed that are declared as
12
+ * renderable content (`*: Component`) and are therefore threaded through the
13
+ * slot channel. A content read `{props.<name>}` of such a prop compiles to
14
+ * {@link PropSlotRender} instead of a value binding, so the child can render a
15
+ * slot handed to it by a caller that wrote `name={<div/>}`.
16
+ */
17
+ let __slotProps = null;
10
18
  function parseExprNode(text) {
11
19
  try {
12
20
  const ParserClass = createBaseParser();
@@ -39,6 +47,34 @@ function getForClauseAnnotation(forStart) {
39
47
  function getSource(source, node) {
40
48
  return source.slice(node.start, node.end);
41
49
  }
50
+ /**
51
+ * Returns the source text for a loop/map binding pattern, preserving
52
+ * destructuring (`[a, b]`, `{x, y}`, defaults, rest) while stripping a
53
+ * top-level TS type annotation (`[a, b]: T` → `[a, b]`). Plain identifiers
54
+ * return their name directly so `const x: T` still yields `x`.
55
+ */
56
+ function patternSource(source, node) {
57
+ if (!node)
58
+ return 'item';
59
+ if (node.type === 'Identifier')
60
+ return node.name ?? 'item';
61
+ const end = node.typeAnnotation ? node.typeAnnotation.start : node.end;
62
+ const text = source.slice(node.start, end).trim();
63
+ return text || 'item';
64
+ }
65
+ function mapParamSource(source, param) {
66
+ if (!param)
67
+ return 'item';
68
+ if (param.type === 'Identifier')
69
+ return param.name ?? 'item';
70
+ const end = param.typeAnnotation ? param.typeAnnotation.start : param.end;
71
+ if (typeof param.start === 'number' && typeof end === 'number') {
72
+ const text = source.slice(param.start, end).trim();
73
+ if (text)
74
+ return text;
75
+ }
76
+ return 'item';
77
+ }
42
78
  function collectComponentCalls(nodes, out) {
43
79
  for (const n of nodes) {
44
80
  if (n instanceof ComponentCall) {
@@ -48,6 +84,9 @@ function collectComponentCalls(nodes, out) {
48
84
  else if (n instanceof StaticNode || n instanceof ServerBlock || n instanceof ClientBlock || n instanceof HeadBlock) {
49
85
  collectComponentCalls(n.children, out);
50
86
  }
87
+ else if (n instanceof PropSlot) {
88
+ collectComponentCalls(n.body, out);
89
+ }
51
90
  else if (n instanceof MapRegion) {
52
91
  collectComponentCalls(n.bodyTemplate, out);
53
92
  collectComponentCalls(n.alternateNodes, out);
@@ -281,10 +320,99 @@ function processAttribute(source, attr) {
281
320
  const expr = attr.value.expression;
282
321
  if (expr.type === 'Literal')
283
322
  return { name, value: String(expr.value) };
323
+ // A JSX element can never be a DOM attribute value — elements belong to
324
+ // content/slots, not to an attribute slot on an HTML tag. Surfacing a real
325
+ // error here beats a raw `(<div/>)` leaking into compiled JS (the previous
326
+ // behavior crashed with a runtime SyntaxError deep inside codegen).
327
+ if (containsJSX(expr)) {
328
+ throw VeskError.attrJsxElement({ attr: name });
329
+ }
284
330
  return { name, value: toExpression(source, expr) };
285
331
  }
286
332
  return { name, value: '' };
287
333
  }
334
+ /**
335
+ * True when `node` (an expression AST) contains a JSX element or fragment
336
+ * anywhere in its subtree — used to distinguish slot-bearing prop values
337
+ * (`trigger={<Button/>}`, `trigger={open ? <A/> : <B/>}`) from plain ones
338
+ * (`align={'end'}`, `count={n + 1}`).
339
+ */
340
+ function containsJSX(node) {
341
+ if (!node || typeof node !== 'object')
342
+ return false;
343
+ if (node.type === 'JSXElement' || node.type === 'JSXFragment')
344
+ return true;
345
+ if (node.type === 'JSXExpressionContainer')
346
+ return containsJSX(node.expression);
347
+ // TS-only position holders (type annotations, parameter names) never contain
348
+ // JSX — skipping them avoids walking TS structure.
349
+ for (const key of [
350
+ 'expression', 'object', 'property', 'callee', 'arguments', 'test',
351
+ 'consequent', 'alternate', 'left', 'right', 'init', 'elements', 'params', 'body',
352
+ ]) {
353
+ const child = node[key];
354
+ if (Array.isArray(child)) {
355
+ for (const c of child)
356
+ if (containsJSX(c))
357
+ return true;
358
+ }
359
+ else if (child && containsJSX(child)) {
360
+ return true;
361
+ }
362
+ }
363
+ return false;
364
+ }
365
+ /**
366
+ * Returns the prop name when `expr` is a bare `props.<name>` read, else null.
367
+ */
368
+ function slotReadPropName(expr) {
369
+ if (expr.type === 'MemberExpression' && !expr.computed &&
370
+ expr.object.type === 'Identifier' && expr.object.name === 'props' &&
371
+ expr.property.type === 'Identifier') {
372
+ return expr.property.name;
373
+ }
374
+ return null;
375
+ }
376
+ /**
377
+ * Parses an inline component props type (`{ trigger: Component; ... }`) and
378
+ * returns the set of prop names declared as renderable content — any member
379
+ * whose type text mentions `Component`. Those props may be handed a JSX
380
+ * element at the call site and are read back with `{props.<name>}` as slots.
381
+ */
382
+ function slotPropNamesFromType(propsType) {
383
+ const out = new Set();
384
+ if (!propsType)
385
+ return out;
386
+ const trimmed = propsType.trim();
387
+ if (trimmed.startsWith('{')) {
388
+ const inner = findBalancedEnd(trimmed, 0) === trimmed.length - 1
389
+ ? trimmed.slice(1, -1)
390
+ : trimmed;
391
+ for (const part of splitTopLevel(inner, ';')) {
392
+ const colon = findTopLevelColon(part);
393
+ if (colon === -1)
394
+ continue;
395
+ const namePart = part.slice(0, colon).trim().replace(/^\$/, '').replace(/\?$/, '').trim();
396
+ const typePart = part.slice(colon + 1).trim();
397
+ if (namePart && typePart.includes('Component'))
398
+ out.add(namePart);
399
+ }
400
+ }
401
+ return out;
402
+ }
403
+ function findTopLevelColon(text) {
404
+ let depth = 0;
405
+ for (let i = 0; i < text.length; i++) {
406
+ const ch = text[i];
407
+ if (ch === '(' || ch === '[' || ch === '{' || ch === '<')
408
+ depth++;
409
+ else if (ch === ')' || ch === ']' || ch === '}')
410
+ depth = Math.max(0, depth - 1);
411
+ else if (ch === ':' && depth === 0)
412
+ return i;
413
+ }
414
+ return -1;
415
+ }
288
416
  /**
289
417
  * Recognizes a statement-mode `if (cond)` opening among JSX children.
290
418
  * Returns the condition source, or null when `text` does not open an if
@@ -433,7 +561,7 @@ function processJSXChildren(source, children) {
433
561
  const exprText = ofParts[1].trim();
434
562
  const arrExpr = new Expression(exprText, [], parseExprNode(exprText), null);
435
563
  const rawFor = hasForPrefix(child.value);
436
- const ann = rawFor ? getForClauseAnnotation(child.start + rawFor) : null;
564
+ const ann = rawFor !== -1 ? getForClauseAnnotation(child.start + rawFor) : null;
437
565
  const keyExpr = ann?.keyRange ? new Expression(source.slice(ann.keyRange[0], ann.keyRange[1])) : null;
438
566
  const indexVar = ann?.indexName ?? null;
439
567
  let alternate = [];
@@ -470,7 +598,7 @@ function processJSXChildren(source, children) {
470
598
  }
471
599
  if (isMapCall(expr)) {
472
600
  const arrowFn = expr.arguments[0];
473
- const itemVar = arrowFn.params[0]?.name ?? 'item';
601
+ const itemVar = mapParamSource(source, arrowFn.params[0]);
474
602
  const indexVar = arrowFn.params[1]?.name ?? null;
475
603
  const bodyNodes = processJSXCallbackBody(source, arrowFn.body);
476
604
  const arrayExpr = toExpression(source, expr.callee.object);
@@ -502,6 +630,16 @@ function processJSXChildren(source, children) {
502
630
  i++;
503
631
  continue;
504
632
  }
633
+ // A content read of a component-declared slot prop (`{props.trigger}`)
634
+ // must render the threaded content — not stringify a fragment.
635
+ {
636
+ const slotName = slotReadPropName(expr);
637
+ if (slotName !== null && __slotProps !== null && __slotProps.has(slotName)) {
638
+ result.push(new PropSlotRender(slotName));
639
+ i++;
640
+ continue;
641
+ }
642
+ }
505
643
  result.push(new DynamicBinding(toExpression(source, expr)));
506
644
  i++;
507
645
  }
@@ -557,7 +695,7 @@ function exprToIR(source, expr) {
557
695
  }
558
696
  if (isMapCall(expr)) {
559
697
  const arrowFn = expr.arguments[0];
560
- const itemVar = arrowFn.params[0]?.name ?? 'item';
698
+ const itemVar = mapParamSource(source, arrowFn.params[0]);
561
699
  const indexVar = arrowFn.params[1]?.name ?? null;
562
700
  const bodyNodes = processJSXCallbackBody(source, arrowFn.body);
563
701
  const arrayExpr = toExpression(source, expr.callee.object);
@@ -580,6 +718,19 @@ function exprToIR(source, expr) {
580
718
  const consequent = exprToIR(source, expr.right);
581
719
  return [new OpaqueDynamicRegion(condExpr, consequent)];
582
720
  }
721
+ // `props.children` (or bare `children`) inside an expression branch must
722
+ // insert the slot nodes — not degrade to a text binding that stringifies
723
+ // the fragment (`String(props.children)` → "[object DocumentFragment]").
724
+ if ((expr.type === 'MemberExpression' && !expr.computed &&
725
+ expr.object.type === 'Identifier' && expr.object.name === 'props' &&
726
+ expr.property.type === 'Identifier' && expr.property.name === 'children')
727
+ || (expr.type === 'Identifier' && expr.name === 'children')) {
728
+ return [new SlotNode()];
729
+ }
730
+ const slotName = slotReadPropName(expr);
731
+ if (slotName !== null && __slotProps !== null && __slotProps.has(slotName)) {
732
+ return [new PropSlotRender(slotName)];
733
+ }
583
734
  return [new DynamicBinding(toExpression(source, expr))];
584
735
  }
585
736
  /**
@@ -633,18 +784,18 @@ function processJSXElement(source, element) {
633
784
  // actual in-scope value instead of `document.createElement("it.icon")` or a
634
785
  // registry lookup by dotted string.
635
786
  if (nameNode && nameNode.type === 'JSXMemberExpression') {
636
- const { props, spreadProps } = extractProps(source, element);
787
+ const { props, spreadProps, slots } = extractProps(source, element);
637
788
  const children = selfClosing ? [] : processJSXChildren(source, element.children || []);
638
- return [new ComponentCall(tagName, props, children, spreadProps, element.start, getSource(source, nameNode))];
789
+ return [new ComponentCall(tagName, props, [...children, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start, getSource(source, nameNode))];
639
790
  }
640
791
  if (!isHTMLTag(tagName) && selfClosing) {
641
- const { props, spreadProps } = extractProps(source, element);
642
- return [new ComponentCall(tagName, props, [], spreadProps, element.start)];
792
+ const { props, spreadProps, slots } = extractProps(source, element);
793
+ return [new ComponentCall(tagName, props, slots.map((s) => new PropSlot(s.name, s.nodes)), spreadProps, element.start)];
643
794
  }
644
795
  if (!isHTMLTag(tagName)) {
645
- const { props, spreadProps } = extractProps(source, element);
796
+ const { props, spreadProps, slots } = extractProps(source, element);
646
797
  const children = processJSXChildren(source, element.children || []);
647
- return [new ComponentCall(tagName, props, children, spreadProps, element.start)];
798
+ return [new ComponentCall(tagName, props, [...children, ...slots.map((s) => new PropSlot(s.name, s.nodes))], spreadProps, element.start)];
648
799
  }
649
800
  const attributes = element.openingElement.attributes
650
801
  .filter((attr) => attr.type !== 'JSXSpreadAttribute')
@@ -677,22 +828,34 @@ function processJSXElement(source, element) {
677
828
  function extractProps(source, element) {
678
829
  const props = [];
679
830
  const spreadProps = [];
831
+ const slots = [];
680
832
  for (const attr of element.openingElement.attributes) {
681
833
  if (attr.type === 'JSXSpreadAttribute') {
682
834
  spreadProps.push(toExpression(source, attr.argument));
683
835
  }
684
836
  else {
685
- props.push({
686
- name: attr.name.type === 'JSXIdentifier' ? attr.name.name : getSource(source, attr.name),
687
- value: attr.value === null
688
- ? new Expression('true')
689
- : attr.value.type === 'JSXExpressionContainer'
690
- ? toExpression(source, attr.value.expression)
691
- : new Expression(JSON.stringify(attr.value.value)),
692
- });
837
+ const name = attr.name.type === 'JSXIdentifier' ? attr.name.name : getSource(source, attr.name);
838
+ let value;
839
+ if (attr.value === null) {
840
+ value = new Expression('true');
841
+ }
842
+ else if (attr.value.type === 'JSXExpressionContainer') {
843
+ const expr = attr.value.expression;
844
+ // JSX elements as prop values are named content slots (`trigger={<Button/>}`),
845
+ // not scalar values — the call site hoists them into the slot channel.
846
+ if (containsJSX(expr)) {
847
+ slots.push({ name, nodes: exprToIR(source, expr) });
848
+ continue;
849
+ }
850
+ value = toExpression(source, expr);
851
+ }
852
+ else {
853
+ value = new Expression(JSON.stringify(attr.value.value));
854
+ }
855
+ props.push({ name, value });
693
856
  }
694
857
  }
695
- return { props, spreadProps };
858
+ return { props, spreadProps, slots };
696
859
  }
697
860
  function buildGuardChain(source, guardClauses, mainReturn) {
698
861
  const mainBody = [];
@@ -842,9 +1005,16 @@ function processIfStatement(source, stmt) {
842
1005
  function processForStatement(source, stmt, alternate = []) {
843
1006
  if (stmt.type === 'ForOfStatement') {
844
1007
  const left = stmt.left;
845
- const itemVar = left.type === 'VariableDeclaration'
846
- ? left.declarations[0]?.id?.name ?? 'item'
847
- : left.name ?? 'item';
1008
+ let itemVar = 'item';
1009
+ if (left.type === 'VariableDeclaration') {
1010
+ itemVar = patternSource(source, left.declarations[0]?.id);
1011
+ }
1012
+ else if (left.type === 'Identifier') {
1013
+ itemVar = left.name ?? 'item';
1014
+ }
1015
+ else if (typeof left.start === 'number' && typeof left.end === 'number') {
1016
+ itemVar = source.slice(left.start, left.end).trim() || 'item';
1017
+ }
848
1018
  const arrayExpr = toExpression(source, stmt.right);
849
1019
  const bodyTemplate = processBlockBody(source, stmt.body);
850
1020
  const ann = getForClauseAnnotation(stmt.start);
@@ -1112,6 +1282,7 @@ function idxOfQuote(s, from) {
1112
1282
  }
1113
1283
  export function generateIR(ast, source, filename) {
1114
1284
  __vskAnnotations = ast.__vskAnnotations ?? [];
1285
+ __slotProps = null;
1115
1286
  const file = filename || '';
1116
1287
  const components = [];
1117
1288
  const imports = [];
@@ -1206,6 +1377,11 @@ export function generateIR(ast, source, filename) {
1206
1377
  const propsType = getPropsType(inner.params, source);
1207
1378
  const bodyStmts = inner.body.body;
1208
1379
  const isClientComp = !!inner.client;
1380
+ // Slot props are declared at the component boundary (`trigger: Component`),
1381
+ // so content reads of `props.<name>` compile to slot renders instead of
1382
+ // value bindings for THIS component only.
1383
+ const prevSlotProps = __slotProps;
1384
+ __slotProps = slotPropNamesFromType(propsType);
1209
1385
  if (isStatementMode(bodyStmts)) {
1210
1386
  const raw = processStatementModeBody(source, bodyStmts, file);
1211
1387
  const { body, css } = extractStyle(raw);
@@ -1213,6 +1389,7 @@ export function generateIR(ast, source, filename) {
1213
1389
  const comp = new ComponentIR(name, paramNames, body, { mode: 'statement', exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType });
1214
1390
  comp.style = css;
1215
1391
  components.push(comp);
1392
+ __slotProps = prevSlotProps;
1216
1393
  }
1217
1394
  else {
1218
1395
  const guardClauses = [];
@@ -1261,6 +1438,7 @@ export function generateIR(ast, source, filename) {
1261
1438
  const comp = new ComponentIR(name, paramNames, body, { exported, defaultExport, isClient: inner.client, isAsync: inner.async, ssrAwait: componentUsesFetch(body), propsType });
1262
1439
  comp.style = css;
1263
1440
  components.push(comp);
1441
+ __slotProps = prevSlotProps;
1264
1442
  }
1265
1443
  }
1266
1444
  const asyncNames = new Set(components.filter((c) => c.isAsync || c.ssrAwait).map((c) => c.name));
package/dist/ir.d.ts CHANGED
@@ -104,6 +104,29 @@ export declare class ComponentCall {
104
104
  export declare class SlotNode {
105
105
  constructor();
106
106
  }
107
+ /**
108
+ * A named content slot threaded to a component through a prop that was given a
109
+ * JSX element value at the call site (`<Popover trigger={<Button/>}>`). The
110
+ * prop is neither a scalar value nor JSON-able — it is renderable content, so
111
+ * codegen hoists the slot body and passes it under the prop name using the
112
+ * exact same channel as `children` (a serialized string IIFE on the server, a
113
+ * fresh DocumentFragment on the client). Child components draw it back with
114
+ * `{props.<name>}`, which compiles to a {@link PropSlotRender}.
115
+ */
116
+ export declare class PropSlot {
117
+ propName: string;
118
+ body: IRNode[];
119
+ constructor(propName: string, body: IRNode[]);
120
+ }
121
+ /**
122
+ * A content read of a slot prop (`{props.trigger}`). The runtime value behind
123
+ * it is threaded through the same channel as `children`, so emitting it on the
124
+ * server pushes the serialized string and on the client appends the fragment.
125
+ */
126
+ export declare class PropSlotRender {
127
+ propName: string;
128
+ constructor(propName: string);
129
+ }
107
130
  export declare class WhileLoop {
108
131
  condition: Expression;
109
132
  bodyTemplate: IRNode[];
@@ -163,5 +186,5 @@ export declare class HeadBlock {
163
186
  children: IRNode[];
164
187
  constructor(children: IRNode[]);
165
188
  }
166
- export type IRNode = StaticNode | TextNode | DynamicBinding | OpaqueDynamicRegion | MapRegion | WhileLoop | SwitchBlock | TryCatch | ForLoop | TrackDecl | RuntimeStatement | ComponentRef | ComponentCall | ServerBlock | ClientBlock | HeadBlock | SlotNode;
189
+ export type IRNode = StaticNode | TextNode | DynamicBinding | OpaqueDynamicRegion | MapRegion | WhileLoop | SwitchBlock | TryCatch | ForLoop | TrackDecl | RuntimeStatement | ComponentRef | ComponentCall | ServerBlock | ClientBlock | HeadBlock | SlotNode | PropSlot | PropSlotRender;
167
190
  //# sourceMappingURL=ir.d.ts.map
package/dist/ir.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../src/ir.ts"],"names":[],"mappings":"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"}
package/dist/ir.js CHANGED
@@ -139,6 +139,34 @@ export class ComponentCall {
139
139
  export class SlotNode {
140
140
  constructor() { }
141
141
  }
142
+ /**
143
+ * A named content slot threaded to a component through a prop that was given a
144
+ * JSX element value at the call site (`<Popover trigger={<Button/>}>`). The
145
+ * prop is neither a scalar value nor JSON-able — it is renderable content, so
146
+ * codegen hoists the slot body and passes it under the prop name using the
147
+ * exact same channel as `children` (a serialized string IIFE on the server, a
148
+ * fresh DocumentFragment on the client). Child components draw it back with
149
+ * `{props.<name>}`, which compiles to a {@link PropSlotRender}.
150
+ */
151
+ export class PropSlot {
152
+ propName;
153
+ body;
154
+ constructor(propName, body) {
155
+ this.propName = propName;
156
+ this.body = body;
157
+ }
158
+ }
159
+ /**
160
+ * A content read of a slot prop (`{props.trigger}`). The runtime value behind
161
+ * it is threaded through the same channel as `children`, so emitting it on the
162
+ * server pushes the serialized string and on the client appends the fragment.
163
+ */
164
+ export class PropSlotRender {
165
+ propName;
166
+ constructor(propName) {
167
+ this.propName = propName;
168
+ }
169
+ }
142
170
  export class WhileLoop {
143
171
  condition;
144
172
  bodyTemplate;
@@ -41,10 +41,31 @@ export declare function readSsrSource(absPath: string): {
41
41
  raw: string;
42
42
  ast: ReturnType<typeof parse> | null;
43
43
  } | null;
44
+ /** Nearest `tsconfig.json` at or above `fromDir`, or null. */
45
+ export declare function findTsconfigPath(fromDir: string): string | null;
46
+ /**
47
+ * Resolves a tsconfig-alias specifier (`@/x`, `@app/x`) to an existing file via
48
+ * the nearest tsconfig's `baseUrl` + `paths`, or null when the specifier is not
49
+ * aliased or no target exists (caller then falls through to normal resolution).
50
+ */
51
+ export declare function resolveAliasModule(spec: string, fromDir: string): string | null;
52
+ /**
53
+ * Resolves a relative import specifier to an absolute file path for a bundler
54
+ * (esbuild/rollup) to consume. An explicit extension is preserved — `./x.ts`
55
+ * stays `./x.ts` and must never become `./x.ts.ts`. An extensionless specifier
56
+ * is probed against `EXTENSIONS` (then `.vsk`, so component imports resolve),
57
+ * and falls back to `.ts` so the bundler reports the missing file by name.
58
+ * tsconfig `paths` aliases (`@/x`, `@app/x`) resolve against the app tsconfig;
59
+ * other bare/absolute specifiers are returned unchanged. This is the single
60
+ * source of truth for every relative-import rewrite (SSR loader and client
61
+ * chunk bundler).
62
+ */
63
+ export declare function resolveImportPath(spec: string, fromDir: string): string;
44
64
  /**
45
65
  * Resolves a specifier to an absolute file path (or a `BUILTIN_PREFIX` marker
46
66
  * for Node builtins). Relative/absolute localities use extension probing;
47
- * bare specifiers (`npm-package`, `pkg/subpath`, `node:fs`, `fs`) prefer
67
+ * tsconfig `paths` aliases (`@/x`, `@app/x`) resolve against the app tsconfig;
68
+ * other bare specifiers (`npm-package`, `pkg/subpath`, `node:fs`, `fs`) prefer
48
69
  * Node's own resolver — which understands `exports` maps, conditions, scoped
49
70
  * packages and builtins — and fall back to a `node_modules` walk-up.
50
71
  *
@@ -1 +1 @@
1
- {"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AA2ElD,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC1F;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAQpE;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,IAAI,CAuBN;AAiBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAiE7E;AA6BD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAe3G;AA8TD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8BlF;AAoJD,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAiGxF;AAaD,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;CACd;AAoDD,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAuCxF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,SAAS,EAAE,eAAe,GACzB,iBAAiB,EAAE,CAiBrB"}
1
+ {"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"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"}