@fluixi/compiler 1.0.0-alpha.105 → 1.0.0-alpha.106

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 (71) hide show
  1. package/dist/analyze/static-graph.cjs +1 -1
  2. package/dist/analyze/static-graph.mjs +1 -1
  3. package/dist/{babel-USPHNEJF.mjs → babel-HJY4RVAV.mjs} +33 -20
  4. package/dist/{chunk-OQYQ7UTD.mjs → chunk-4XEOMQ57.mjs} +1 -1
  5. package/dist/{chunk-EK4OMGTU.mjs → chunk-JUFI6IR3.mjs} +1 -1
  6. package/dist/{chunk-5GAYDAAC.mjs → chunk-LCQHL2VQ.mjs} +132 -10
  7. package/dist/{chunk-XBAQME2V.mjs → chunk-LGUZRHYN.mjs} +2 -2
  8. package/dist/{chunk-O6OBEV4V.mjs → chunk-TDN5MYWI.mjs} +1 -1
  9. package/dist/{chunk-EQIIWIEU.mjs → chunk-W7DYOMXJ.mjs} +2 -2
  10. package/dist/{chunk-FMIIK5UM.mjs → chunk-WHEDRMNR.mjs} +1 -1
  11. package/dist/codegen/backends/imperative.cjs +130 -8
  12. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  13. package/dist/codegen/backends/imperative.js +62 -0
  14. package/dist/codegen/backends/imperative.mjs +130 -8
  15. package/dist/codegen/partial-template.cjs +80 -8
  16. package/dist/codegen/partial-template.d.cts +21 -4
  17. package/dist/codegen/partial-template.d.ts +21 -4
  18. package/dist/codegen/partial-template.d.ts.map +1 -1
  19. package/dist/codegen/partial-template.js +0 -0
  20. package/dist/codegen/partial-template.mjs +80 -8
  21. package/dist/codegen/serialize-static.cjs +1 -0
  22. package/dist/codegen/serialize-static.d.cts +8 -0
  23. package/dist/codegen/serialize-static.d.ts +8 -0
  24. package/dist/codegen/serialize-static.d.ts.map +1 -1
  25. package/dist/codegen/serialize-static.js +1 -1
  26. package/dist/codegen/serialize-static.mjs +1 -0
  27. package/dist/frontend/babel/build-ir-html.cjs +149 -21
  28. package/dist/frontend/babel/build-ir-html.d.cts +3 -1
  29. package/dist/frontend/babel/build-ir-html.d.ts +3 -1
  30. package/dist/frontend/babel/build-ir-html.d.ts.map +1 -1
  31. package/dist/frontend/babel/build-ir-html.mjs +149 -21
  32. package/dist/frontend/babel/build-ir.cjs +149 -21
  33. package/dist/frontend/babel/build-ir.d.cts +11 -2
  34. package/dist/frontend/babel/build-ir.d.ts +11 -2
  35. package/dist/frontend/babel/build-ir.d.ts.map +1 -1
  36. package/dist/frontend/babel/build-ir.js +15 -9
  37. package/dist/frontend/babel/build-ir.mjs +149 -21
  38. package/dist/frontend/babel/index.cjs +160 -25
  39. package/dist/frontend/babel/index.mjs +160 -25
  40. package/dist/frontend/babel/lower-template.cjs +149 -21
  41. package/dist/frontend/babel/lower-template.d.cts +2 -1
  42. package/dist/frontend/babel/lower-template.d.ts +2 -1
  43. package/dist/frontend/babel/lower-template.d.ts.map +1 -1
  44. package/dist/frontend/babel/lower-template.js +4 -4
  45. package/dist/frontend/babel/lower-template.mjs +149 -21
  46. package/dist/frontend/babel/plugin.cjs +158 -23
  47. package/dist/frontend/babel/plugin.js +9 -2
  48. package/dist/frontend/babel/plugin.mjs +158 -23
  49. package/dist/index.cjs +131 -9
  50. package/dist/index.mjs +131 -9
  51. package/dist/integrations.cjs +165 -33
  52. package/dist/integrations.mjs +11 -11
  53. package/dist/lower/compile-template.cjs +131 -9
  54. package/dist/lower/compile-template.mjs +131 -9
  55. package/dist/lower/jsx.cjs +130 -8
  56. package/dist/lower/jsx.mjs +130 -8
  57. package/dist/lower/template.cjs +130 -8
  58. package/dist/lower/template.mjs +130 -8
  59. package/dist/resolve/builtins.cjs +1 -1
  60. package/dist/resolve/builtins.mjs +1 -1
  61. package/dist/{server-fns-7Y25MR3B.mjs → server-fns-WZJK4BJE.mjs} +5 -5
  62. package/dist/{server-functions-43CFKXY3.mjs → server-functions-4KTFFEO3.mjs} +3 -3
  63. package/dist/transform/index.cjs +135 -16
  64. package/dist/transform/index.mjs +135 -16
  65. package/dist/transform/templates.cjs +134 -15
  66. package/dist/transform/templates.d.ts.map +1 -1
  67. package/dist/transform/templates.js +4 -8
  68. package/dist/transform/templates.mjs +134 -15
  69. package/dist/{transform-YUDW7K4J.mjs → transform-NO46NFQH.mjs} +11 -14
  70. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  71. package/package.json +4 -4
@@ -30,7 +30,7 @@ function gen(node) {
30
30
  * for it (build-ir -> emit), so the resulting expression is plain JS. Runtime
31
31
  * symbols used by the nested code are added to `used`.
32
32
  */
33
- function transformNestedJSX(node, used, onNested) {
33
+ function transformNestedJSX(node, used, onNested, emit) {
34
34
  const clone = t.cloneNode(node, true);
35
35
  const file = t.file(t.program([t.expressionStatement(clone)]));
36
36
  let changed = false;
@@ -48,9 +48,12 @@ function transformNestedJSX(node, used, onNested) {
48
48
  const jsx = path.node;
49
49
  // Resolve before emitting: the emitted call refers to the component by name,
50
50
  // and whoever injects the import has to have seen it.
51
- const nestedIR = buildIR(jsx, used, onNested);
51
+ const nestedIR = buildIR(jsx, used, onNested, emit);
52
52
  onNested?.(nestedIR);
53
- const { code, imports, templates } = imperativeBackend.emit(nestedIR, {});
53
+ const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
54
+ templateClone: emit?.templateClone,
55
+ partialTemplates: emit?.partialTemplates ?? true,
56
+ });
54
57
  emitInto(path, inlineTemplates(code, templates), imports);
55
58
  },
56
59
  // Nested html templates compose: ${cond ? html`...` : html`...`},
@@ -59,9 +62,12 @@ function transformNestedJSX(node, used, onNested) {
59
62
  const tag = path.node.tag;
60
63
  if (!t.isIdentifier(tag) || (tag.name !== 'html' && tag.name !== 'svg'))
61
64
  return;
62
- const ir = buildIRFromHtml(path.node, used, { svg: tag.name === 'svg', onNested });
65
+ const ir = buildIRFromHtml(path.node, used, { svg: tag.name === 'svg', onNested, emit });
63
66
  onNested?.(ir);
64
- const { code, imports, templates } = imperativeBackend.emit(ir, {});
67
+ const { code, imports, templates } = imperativeBackend.emit(ir, {
68
+ templateClone: emit?.templateClone,
69
+ partialTemplates: emit?.partialTemplates ?? true,
70
+ });
65
71
  emitInto(path, inlineTemplates(code, templates), imports);
66
72
  },
67
73
  });
@@ -70,8 +76,8 @@ function transformNestedJSX(node, used, onNested) {
70
76
  : node;
71
77
  }
72
78
  /** Stringify an expression, compiling any JSX nested inside it first. */
73
- export function genExpr(node, used, onNested) {
74
- return gen(transformNestedJSX(node, used, onNested));
79
+ export function genExpr(node, used, onNested, emit) {
80
+ return gen(transformNestedJSX(node, used, onNested, emit));
75
81
  }
76
82
  export const SVG_TAGS = new Set([
77
83
  'svg', 'path', 'circle', 'rect', 'line', 'polygon', 'polyline',
@@ -110,14 +116,14 @@ export function isReactiveExpr(node) {
110
116
  * front-end supplies is how an expression becomes source, `genExpr`, which also
111
117
  * compiles any JSX or `` html`` `` nested inside it.
112
118
  */
113
- export function buildIR(node, used = new Set(), onNested) {
119
+ export function buildIR(node, used = new Set(), onNested, emit) {
114
120
  const ir = buildJsxIR(node, {
115
121
  code: (n) =>
116
122
  // A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
117
123
  // through the nested-JSX compile: it only ever needs printing.
118
124
  n.type === 'JSXMemberExpression'
119
125
  ? gen(n)
120
- : genExpr(n, used, onNested),
126
+ : genExpr(n, used, onNested, emit),
121
127
  used,
122
128
  });
123
129
  return ir;
@@ -108,10 +108,64 @@ function isHole(node) {
108
108
  function isTemplateChild(node) {
109
109
  return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
110
110
  }
111
+ var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
112
+ function disposition(prop) {
113
+ if (prop.kind === "spread") return null;
114
+ if (prop.name === "ref") return "ref";
115
+ if (prop.name === "use") return "use";
116
+ if (prop.kind === "event") return prop.event ? "event" : null;
117
+ if (prop.kind === "prop") return "property";
118
+ if (prop.kind !== "attr") return null;
119
+ const name = prop.name;
120
+ if (name.startsWith("on:")) return "nativeEvent";
121
+ if (name.startsWith("prop:")) return "property";
122
+ if (name.startsWith("attr:")) return "attr";
123
+ if (name.startsWith("bool:")) return "boolAttr";
124
+ if (name === "className" || name === "class") {
125
+ return isPlainLiteralAttr(prop) ? "serialize" : "class";
126
+ }
127
+ if (name === "classList") {
128
+ if (isPlainLiteralAttr(prop)) return "serialize";
129
+ return prop.reactive ? "classListDynamic" : "classList";
130
+ }
131
+ if (name === "style") {
132
+ if (isPlainLiteralAttr(prop)) return "serialize";
133
+ return prop.reactive ? "styleDynamic" : "style";
134
+ }
135
+ if (name.includes(":")) return null;
136
+ if (PROPERTY_ONLY.has(name)) return null;
137
+ if (PROPERTY_BINDS.has(name)) return "property";
138
+ if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
139
+ return "attr";
140
+ }
141
+ function effectiveProps(el) {
142
+ const order = [];
143
+ const byName = /* @__PURE__ */ new Map();
144
+ for (const prop of el.props) {
145
+ if (!byName.has(prop.name)) order.push(prop.name);
146
+ byName.set(prop.name, prop);
147
+ }
148
+ return order.map((name) => byName.get(name));
149
+ }
150
+ function propPlan(el) {
151
+ const custom = el.tag.includes("-");
152
+ const plan = { serialize: [], bindings: [] };
153
+ for (const prop of effectiveProps(el)) {
154
+ const kind = disposition(prop);
155
+ if (kind === null) return null;
156
+ if (kind === "serialize") {
157
+ plan.serialize.push(prop);
158
+ continue;
159
+ }
160
+ if (custom) return null;
161
+ plan.bindings.push({ prop, kind });
162
+ }
163
+ return plan;
164
+ }
111
165
  function isTemplateElement(node) {
112
166
  if (node.svg) return false;
113
167
  if (isRawTextElement(node.tag)) return false;
114
- if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
168
+ if (!propPlan(node)) return false;
115
169
  return node.children.every((c) => isTemplateChild(c) || isHole(c));
116
170
  }
117
171
  function containsHole(node) {
@@ -119,6 +173,15 @@ function containsHole(node) {
119
173
  const children = node.children;
120
174
  return children ? children.some(containsHole) : false;
121
175
  }
176
+ function containsBinding(node) {
177
+ if (node.kind !== "element") return false;
178
+ const plan = propPlan(node);
179
+ if (plan && plan.bindings.length > 0) return true;
180
+ return node.children.some(containsBinding);
181
+ }
182
+ function interesting(node) {
183
+ return containsHole(node) || containsBinding(node);
184
+ }
122
185
  function addressable(el) {
123
186
  for (let i = 0; i < el.children.length; i++) {
124
187
  const child = el.children[i];
@@ -132,9 +195,10 @@ function addressable(el) {
132
195
  function planPartialTemplate(root) {
133
196
  if (!isTemplateElement(root)) return null;
134
197
  if (!addressable(root)) return null;
135
- if (!root.children.some(containsHole)) return null;
198
+ if (!interesting(root)) return null;
136
199
  const steps = [];
137
200
  const holes = [];
201
+ const bindings = [];
138
202
  let refCount = 0;
139
203
  const declare = (expr) => {
140
204
  const ref = `_n$${refCount++}`;
@@ -142,11 +206,17 @@ function planPartialTemplate(root) {
142
206
  return ref;
143
207
  };
144
208
  walk(root, "_el$");
145
- return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
209
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
146
210
  function walk(el, elementRef) {
211
+ const plan = propPlan(el);
212
+ if (plan) {
213
+ for (const binding of plan.bindings) {
214
+ bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
215
+ }
216
+ }
147
217
  let last = -1;
148
218
  el.children.forEach((child, i) => {
149
- if (containsHole(child)) last = i;
219
+ if (interesting(child)) last = i;
150
220
  });
151
221
  let previous = null;
152
222
  for (let i = 0; i <= last; i++) {
@@ -160,19 +230,21 @@ function planPartialTemplate(root) {
160
230
  continue;
161
231
  }
162
232
  const ref = declare(expr);
163
- if (child.kind === "element" && containsHole(child)) walk(child, ref);
233
+ if (child.kind === "element" && interesting(child)) walk(child, ref);
164
234
  previous = ref;
165
235
  }
166
236
  }
167
237
  }
168
238
  function serializeWithMarkers(el) {
169
- return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
239
+ return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
170
240
  }
171
- function withSentinels(el) {
241
+ function templateTree(el) {
242
+ const plan = propPlan(el);
172
243
  return {
173
244
  ...el,
245
+ props: plan ? plan.serialize : [],
174
246
  children: el.children.map(
175
- (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
247
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
176
248
  )
177
249
  };
178
250
  }
@@ -445,6 +517,55 @@ function emitComponent(name, props, children, used, templates, at) {
445
517
  const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
446
518
  return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
447
519
  }
520
+ function bindingTarget(binding) {
521
+ const name = binding.prop.name;
522
+ if (binding.kind === "boolAttr") return name.slice("bool:".length);
523
+ if (name.startsWith("prop:")) return name.slice("prop:".length);
524
+ if (name.startsWith("attr:")) return name.slice("attr:".length);
525
+ return htmlAttrName(name);
526
+ }
527
+ function bindingStatement(binding, used) {
528
+ const { ref, prop, kind } = binding;
529
+ const value = propValue(prop);
530
+ switch (kind) {
531
+ case "class":
532
+ used.add("setClassName");
533
+ return `setClassName(${ref}, ${value});`;
534
+ case "classList":
535
+ used.add("setClassList");
536
+ return `setClassList(${ref}, ${value}, []);`;
537
+ case "classListDynamic":
538
+ used.add("setDynamicClassList");
539
+ return `setDynamicClassList(${ref}, ${value});`;
540
+ case "style":
541
+ used.add("setStyle");
542
+ return `setStyle(${ref}, ${value}, []);`;
543
+ case "styleDynamic":
544
+ used.add("setDynamicStyle");
545
+ return `setDynamicStyle(${ref}, ${value});`;
546
+ case "attr":
547
+ used.add("setDynamicAttribute");
548
+ return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
549
+ case "property":
550
+ used.add("setDynamicProperty");
551
+ return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
552
+ case "boolAttr":
553
+ used.add("setDynamicBoolAttribute");
554
+ return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
555
+ case "event":
556
+ used.add("addDelegatedEventListener");
557
+ return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
558
+ case "nativeEvent":
559
+ used.add("addNativeEventListener");
560
+ return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
561
+ case "ref":
562
+ used.add("handleRef");
563
+ return `handleRef(${value}, ${ref});`;
564
+ case "use":
565
+ used.add("applyUse");
566
+ return `applyUse(${ref}, ${value});`;
567
+ }
568
+ }
448
569
  function staticAttrAssignment(el, prop) {
449
570
  const name = htmlAttrName(prop.name);
450
571
  const value = prop.literal;
@@ -495,6 +616,7 @@ function emitNode(node, used, templates) {
495
616
  `const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
496
617
  ];
497
618
  for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
619
+ for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
498
620
  for (const hole of plan.holes) {
499
621
  lines.push(
500
622
  `insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
@@ -1347,16 +1469,16 @@ var generate = _generate.default ?? _generate;
1347
1469
  function gen(node) {
1348
1470
  return generate(node, { concise: true }).code;
1349
1471
  }
1350
- function bindHole(expr, used, onNested) {
1472
+ function bindHole(expr, used, onNested, emit) {
1351
1473
  const hole = {
1352
- code: genExpr(expr, used, onNested),
1474
+ code: genExpr(expr, used, onNested, emit),
1353
1475
  reactive: isReactiveExpr(expr)
1354
1476
  };
1355
1477
  if (t.isArrowFunctionExpression(expr) && !t.isBlockStatement(expr.body)) {
1356
1478
  const body = expr.body;
1357
1479
  hole.arrow = {
1358
1480
  params: expr.params.map((p) => gen(p)),
1359
- body: genExpr(body, used, onNested),
1481
+ body: genExpr(body, used, onNested, emit),
1360
1482
  bodyReactive: isReactiveExpr(body)
1361
1483
  };
1362
1484
  }
@@ -1365,7 +1487,7 @@ function bindHole(expr, used, onNested) {
1365
1487
  }
1366
1488
  function lowerHtmlTemplate(node, used, opts = {}) {
1367
1489
  const quasi = node.quasi;
1368
- const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
1490
+ const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested, opts.emit));
1369
1491
  return lowerTemplate(buildPieces(quasi), holes, used, opts);
1370
1492
  }
1371
1493
  function buildPieces(quasi) {
@@ -1853,7 +1975,7 @@ var generate2 = _generate2.default ?? _generate2;
1853
1975
  function gen2(node) {
1854
1976
  return generate2(node, { concise: true }).code;
1855
1977
  }
1856
- function transformNestedJSX(node, used, onNested) {
1978
+ function transformNestedJSX(node, used, onNested, emit) {
1857
1979
  const clone = t2.cloneNode(node, true);
1858
1980
  const file = t2.file(t2.program([t2.expressionStatement(clone)]));
1859
1981
  let changed = false;
@@ -1866,9 +1988,12 @@ function transformNestedJSX(node, used, onNested) {
1866
1988
  traverse(file, {
1867
1989
  "JSXElement|JSXFragment"(path) {
1868
1990
  const jsx = path.node;
1869
- const nestedIR = buildIR(jsx, used, onNested);
1991
+ const nestedIR = buildIR(jsx, used, onNested, emit);
1870
1992
  onNested?.(nestedIR);
1871
- const { code, imports, templates } = imperativeBackend.emit(nestedIR, {});
1993
+ const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
1994
+ templateClone: emit?.templateClone,
1995
+ partialTemplates: emit?.partialTemplates ?? true
1996
+ });
1872
1997
  emitInto(path, inlineTemplates(code, templates), imports);
1873
1998
  },
1874
1999
  // Nested html templates compose: ${cond ? html`...` : html`...`},
@@ -1876,16 +2001,19 @@ function transformNestedJSX(node, used, onNested) {
1876
2001
  TaggedTemplateExpression(path) {
1877
2002
  const tag = path.node.tag;
1878
2003
  if (!t2.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
1879
- const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested });
2004
+ const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested, emit });
1880
2005
  onNested?.(ir);
1881
- const { code, imports, templates } = imperativeBackend.emit(ir, {});
2006
+ const { code, imports, templates } = imperativeBackend.emit(ir, {
2007
+ templateClone: emit?.templateClone,
2008
+ partialTemplates: emit?.partialTemplates ?? true
2009
+ });
1882
2010
  emitInto(path, inlineTemplates(code, templates), imports);
1883
2011
  }
1884
2012
  });
1885
2013
  return changed ? file.program.body[0].expression : node;
1886
2014
  }
1887
- function genExpr(node, used, onNested) {
1888
- return gen2(transformNestedJSX(node, used, onNested));
2015
+ function genExpr(node, used, onNested, emit) {
2016
+ return gen2(transformNestedJSX(node, used, onNested, emit));
1889
2017
  }
1890
2018
  var SVG_TAGS2 = /* @__PURE__ */ new Set([
1891
2019
  "svg",
@@ -1904,12 +2032,12 @@ var SVG_TAGS2 = /* @__PURE__ */ new Set([
1904
2032
  function isReactiveExpr(node) {
1905
2033
  return isReactiveShape(shapeOf(node));
1906
2034
  }
1907
- function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
2035
+ function buildIR(node, used = /* @__PURE__ */ new Set(), onNested, emit) {
1908
2036
  const ir = buildJsxIR(node, {
1909
2037
  code: (n) => (
1910
2038
  // A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
1911
2039
  // through the nested-JSX compile: it only ever needs printing.
1912
- n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested)
2040
+ n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested, emit)
1913
2041
  ),
1914
2042
  used
1915
2043
  });