@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
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @fluixi/compiler v1.0.0-alpha.105 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/compiler v1.0.0-alpha.106 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -222,10 +222,64 @@ function isHole(node) {
222
222
  function isTemplateChild(node) {
223
223
  return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
224
224
  }
225
+ var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
226
+ function disposition(prop) {
227
+ if (prop.kind === "spread") return null;
228
+ if (prop.name === "ref") return "ref";
229
+ if (prop.name === "use") return "use";
230
+ if (prop.kind === "event") return prop.event ? "event" : null;
231
+ if (prop.kind === "prop") return "property";
232
+ if (prop.kind !== "attr") return null;
233
+ const name = prop.name;
234
+ if (name.startsWith("on:")) return "nativeEvent";
235
+ if (name.startsWith("prop:")) return "property";
236
+ if (name.startsWith("attr:")) return "attr";
237
+ if (name.startsWith("bool:")) return "boolAttr";
238
+ if (name === "className" || name === "class") {
239
+ return isPlainLiteralAttr(prop) ? "serialize" : "class";
240
+ }
241
+ if (name === "classList") {
242
+ if (isPlainLiteralAttr(prop)) return "serialize";
243
+ return prop.reactive ? "classListDynamic" : "classList";
244
+ }
245
+ if (name === "style") {
246
+ if (isPlainLiteralAttr(prop)) return "serialize";
247
+ return prop.reactive ? "styleDynamic" : "style";
248
+ }
249
+ if (name.includes(":")) return null;
250
+ if (PROPERTY_ONLY.has(name)) return null;
251
+ if (PROPERTY_BINDS.has(name)) return "property";
252
+ if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
253
+ return "attr";
254
+ }
255
+ function effectiveProps(el) {
256
+ const order = [];
257
+ const byName = /* @__PURE__ */ new Map();
258
+ for (const prop of el.props) {
259
+ if (!byName.has(prop.name)) order.push(prop.name);
260
+ byName.set(prop.name, prop);
261
+ }
262
+ return order.map((name) => byName.get(name));
263
+ }
264
+ function propPlan(el) {
265
+ const custom = el.tag.includes("-");
266
+ const plan = { serialize: [], bindings: [] };
267
+ for (const prop of effectiveProps(el)) {
268
+ const kind = disposition(prop);
269
+ if (kind === null) return null;
270
+ if (kind === "serialize") {
271
+ plan.serialize.push(prop);
272
+ continue;
273
+ }
274
+ if (custom) return null;
275
+ plan.bindings.push({ prop, kind });
276
+ }
277
+ return plan;
278
+ }
225
279
  function isTemplateElement(node) {
226
280
  if (node.svg) return false;
227
281
  if (isRawTextElement(node.tag)) return false;
228
- if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
282
+ if (!propPlan(node)) return false;
229
283
  return node.children.every((c) => isTemplateChild(c) || isHole(c));
230
284
  }
231
285
  function containsHole(node) {
@@ -233,6 +287,15 @@ function containsHole(node) {
233
287
  const children = node.children;
234
288
  return children ? children.some(containsHole) : false;
235
289
  }
290
+ function containsBinding(node) {
291
+ if (node.kind !== "element") return false;
292
+ const plan = propPlan(node);
293
+ if (plan && plan.bindings.length > 0) return true;
294
+ return node.children.some(containsBinding);
295
+ }
296
+ function interesting(node) {
297
+ return containsHole(node) || containsBinding(node);
298
+ }
236
299
  function addressable(el) {
237
300
  for (let i = 0; i < el.children.length; i++) {
238
301
  const child = el.children[i];
@@ -246,9 +309,10 @@ function addressable(el) {
246
309
  function planPartialTemplate(root) {
247
310
  if (!isTemplateElement(root)) return null;
248
311
  if (!addressable(root)) return null;
249
- if (!root.children.some(containsHole)) return null;
312
+ if (!interesting(root)) return null;
250
313
  const steps = [];
251
314
  const holes = [];
315
+ const bindings = [];
252
316
  let refCount = 0;
253
317
  const declare = (expr) => {
254
318
  const ref = `_n$${refCount++}`;
@@ -256,11 +320,17 @@ function planPartialTemplate(root) {
256
320
  return ref;
257
321
  };
258
322
  walk2(root, "_el$");
259
- return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
323
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
260
324
  function walk2(el, elementRef) {
325
+ const plan = propPlan(el);
326
+ if (plan) {
327
+ for (const binding of plan.bindings) {
328
+ bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
329
+ }
330
+ }
261
331
  let last = -1;
262
332
  el.children.forEach((child, i) => {
263
- if (containsHole(child)) last = i;
333
+ if (interesting(child)) last = i;
264
334
  });
265
335
  let previous = null;
266
336
  for (let i = 0; i <= last; i++) {
@@ -274,19 +344,21 @@ function planPartialTemplate(root) {
274
344
  continue;
275
345
  }
276
346
  const ref = declare(expr);
277
- if (child.kind === "element" && containsHole(child)) walk2(child, ref);
347
+ if (child.kind === "element" && interesting(child)) walk2(child, ref);
278
348
  previous = ref;
279
349
  }
280
350
  }
281
351
  }
282
352
  function serializeWithMarkers(el) {
283
- return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
353
+ return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
284
354
  }
285
- function withSentinels(el) {
355
+ function templateTree(el) {
356
+ const plan = propPlan(el);
286
357
  return {
287
358
  ...el,
359
+ props: plan ? plan.serialize : [],
288
360
  children: el.children.map(
289
- (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
361
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
290
362
  )
291
363
  };
292
364
  }
@@ -564,6 +636,55 @@ function emitComponent(name, props, children, used, templates, at) {
564
636
  const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
565
637
  return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
566
638
  }
639
+ function bindingTarget(binding) {
640
+ const name = binding.prop.name;
641
+ if (binding.kind === "boolAttr") return name.slice("bool:".length);
642
+ if (name.startsWith("prop:")) return name.slice("prop:".length);
643
+ if (name.startsWith("attr:")) return name.slice("attr:".length);
644
+ return htmlAttrName(name);
645
+ }
646
+ function bindingStatement(binding, used) {
647
+ const { ref, prop, kind } = binding;
648
+ const value = propValue(prop);
649
+ switch (kind) {
650
+ case "class":
651
+ used.add("setClassName");
652
+ return `setClassName(${ref}, ${value});`;
653
+ case "classList":
654
+ used.add("setClassList");
655
+ return `setClassList(${ref}, ${value}, []);`;
656
+ case "classListDynamic":
657
+ used.add("setDynamicClassList");
658
+ return `setDynamicClassList(${ref}, ${value});`;
659
+ case "style":
660
+ used.add("setStyle");
661
+ return `setStyle(${ref}, ${value}, []);`;
662
+ case "styleDynamic":
663
+ used.add("setDynamicStyle");
664
+ return `setDynamicStyle(${ref}, ${value});`;
665
+ case "attr":
666
+ used.add("setDynamicAttribute");
667
+ return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
668
+ case "property":
669
+ used.add("setDynamicProperty");
670
+ return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
671
+ case "boolAttr":
672
+ used.add("setDynamicBoolAttribute");
673
+ return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
674
+ case "event":
675
+ used.add("addDelegatedEventListener");
676
+ return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
677
+ case "nativeEvent":
678
+ used.add("addNativeEventListener");
679
+ return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
680
+ case "ref":
681
+ used.add("handleRef");
682
+ return `handleRef(${value}, ${ref});`;
683
+ case "use":
684
+ used.add("applyUse");
685
+ return `applyUse(${ref}, ${value});`;
686
+ }
687
+ }
567
688
  function staticAttrAssignment(el, prop) {
568
689
  const name = htmlAttrName(prop.name);
569
690
  const value = prop.literal;
@@ -614,6 +735,7 @@ function emitNode(node, used, templates) {
614
735
  `const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
615
736
  ];
616
737
  for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
738
+ for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
617
739
  for (const hole of plan.holes) {
618
740
  lines.push(
619
741
  `insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @fluixi/compiler v1.0.0-alpha.105 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/compiler v1.0.0-alpha.106 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
 
3
3
  // src/analyze/reactive-expr.ts
4
4
  var STABLE_MEMBER = "children";
@@ -175,10 +175,64 @@ function isHole(node) {
175
175
  function isTemplateChild(node) {
176
176
  return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
177
177
  }
178
+ var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
179
+ function disposition(prop) {
180
+ if (prop.kind === "spread") return null;
181
+ if (prop.name === "ref") return "ref";
182
+ if (prop.name === "use") return "use";
183
+ if (prop.kind === "event") return prop.event ? "event" : null;
184
+ if (prop.kind === "prop") return "property";
185
+ if (prop.kind !== "attr") return null;
186
+ const name = prop.name;
187
+ if (name.startsWith("on:")) return "nativeEvent";
188
+ if (name.startsWith("prop:")) return "property";
189
+ if (name.startsWith("attr:")) return "attr";
190
+ if (name.startsWith("bool:")) return "boolAttr";
191
+ if (name === "className" || name === "class") {
192
+ return isPlainLiteralAttr(prop) ? "serialize" : "class";
193
+ }
194
+ if (name === "classList") {
195
+ if (isPlainLiteralAttr(prop)) return "serialize";
196
+ return prop.reactive ? "classListDynamic" : "classList";
197
+ }
198
+ if (name === "style") {
199
+ if (isPlainLiteralAttr(prop)) return "serialize";
200
+ return prop.reactive ? "styleDynamic" : "style";
201
+ }
202
+ if (name.includes(":")) return null;
203
+ if (PROPERTY_ONLY.has(name)) return null;
204
+ if (PROPERTY_BINDS.has(name)) return "property";
205
+ if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
206
+ return "attr";
207
+ }
208
+ function effectiveProps(el) {
209
+ const order = [];
210
+ const byName = /* @__PURE__ */ new Map();
211
+ for (const prop of el.props) {
212
+ if (!byName.has(prop.name)) order.push(prop.name);
213
+ byName.set(prop.name, prop);
214
+ }
215
+ return order.map((name) => byName.get(name));
216
+ }
217
+ function propPlan(el) {
218
+ const custom = el.tag.includes("-");
219
+ const plan = { serialize: [], bindings: [] };
220
+ for (const prop of effectiveProps(el)) {
221
+ const kind = disposition(prop);
222
+ if (kind === null) return null;
223
+ if (kind === "serialize") {
224
+ plan.serialize.push(prop);
225
+ continue;
226
+ }
227
+ if (custom) return null;
228
+ plan.bindings.push({ prop, kind });
229
+ }
230
+ return plan;
231
+ }
178
232
  function isTemplateElement(node) {
179
233
  if (node.svg) return false;
180
234
  if (isRawTextElement(node.tag)) return false;
181
- if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
235
+ if (!propPlan(node)) return false;
182
236
  return node.children.every((c) => isTemplateChild(c) || isHole(c));
183
237
  }
184
238
  function containsHole(node) {
@@ -186,6 +240,15 @@ function containsHole(node) {
186
240
  const children = node.children;
187
241
  return children ? children.some(containsHole) : false;
188
242
  }
243
+ function containsBinding(node) {
244
+ if (node.kind !== "element") return false;
245
+ const plan = propPlan(node);
246
+ if (plan && plan.bindings.length > 0) return true;
247
+ return node.children.some(containsBinding);
248
+ }
249
+ function interesting(node) {
250
+ return containsHole(node) || containsBinding(node);
251
+ }
189
252
  function addressable(el) {
190
253
  for (let i = 0; i < el.children.length; i++) {
191
254
  const child = el.children[i];
@@ -199,9 +262,10 @@ function addressable(el) {
199
262
  function planPartialTemplate(root) {
200
263
  if (!isTemplateElement(root)) return null;
201
264
  if (!addressable(root)) return null;
202
- if (!root.children.some(containsHole)) return null;
265
+ if (!interesting(root)) return null;
203
266
  const steps = [];
204
267
  const holes = [];
268
+ const bindings = [];
205
269
  let refCount = 0;
206
270
  const declare = (expr) => {
207
271
  const ref = `_n$${refCount++}`;
@@ -209,11 +273,17 @@ function planPartialTemplate(root) {
209
273
  return ref;
210
274
  };
211
275
  walk2(root, "_el$");
212
- return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
276
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
213
277
  function walk2(el, elementRef) {
278
+ const plan = propPlan(el);
279
+ if (plan) {
280
+ for (const binding of plan.bindings) {
281
+ bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
282
+ }
283
+ }
214
284
  let last = -1;
215
285
  el.children.forEach((child, i) => {
216
- if (containsHole(child)) last = i;
286
+ if (interesting(child)) last = i;
217
287
  });
218
288
  let previous = null;
219
289
  for (let i = 0; i <= last; i++) {
@@ -227,19 +297,21 @@ function planPartialTemplate(root) {
227
297
  continue;
228
298
  }
229
299
  const ref = declare(expr);
230
- if (child.kind === "element" && containsHole(child)) walk2(child, ref);
300
+ if (child.kind === "element" && interesting(child)) walk2(child, ref);
231
301
  previous = ref;
232
302
  }
233
303
  }
234
304
  }
235
305
  function serializeWithMarkers(el) {
236
- return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
306
+ return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
237
307
  }
238
- function withSentinels(el) {
308
+ function templateTree(el) {
309
+ const plan = propPlan(el);
239
310
  return {
240
311
  ...el,
312
+ props: plan ? plan.serialize : [],
241
313
  children: el.children.map(
242
- (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
314
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
243
315
  )
244
316
  };
245
317
  }
@@ -517,6 +589,55 @@ function emitComponent(name, props, children, used, templates, at) {
517
589
  const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
518
590
  return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
519
591
  }
592
+ function bindingTarget(binding) {
593
+ const name = binding.prop.name;
594
+ if (binding.kind === "boolAttr") return name.slice("bool:".length);
595
+ if (name.startsWith("prop:")) return name.slice("prop:".length);
596
+ if (name.startsWith("attr:")) return name.slice("attr:".length);
597
+ return htmlAttrName(name);
598
+ }
599
+ function bindingStatement(binding, used) {
600
+ const { ref, prop, kind } = binding;
601
+ const value = propValue(prop);
602
+ switch (kind) {
603
+ case "class":
604
+ used.add("setClassName");
605
+ return `setClassName(${ref}, ${value});`;
606
+ case "classList":
607
+ used.add("setClassList");
608
+ return `setClassList(${ref}, ${value}, []);`;
609
+ case "classListDynamic":
610
+ used.add("setDynamicClassList");
611
+ return `setDynamicClassList(${ref}, ${value});`;
612
+ case "style":
613
+ used.add("setStyle");
614
+ return `setStyle(${ref}, ${value}, []);`;
615
+ case "styleDynamic":
616
+ used.add("setDynamicStyle");
617
+ return `setDynamicStyle(${ref}, ${value});`;
618
+ case "attr":
619
+ used.add("setDynamicAttribute");
620
+ return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
621
+ case "property":
622
+ used.add("setDynamicProperty");
623
+ return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
624
+ case "boolAttr":
625
+ used.add("setDynamicBoolAttribute");
626
+ return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
627
+ case "event":
628
+ used.add("addDelegatedEventListener");
629
+ return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
630
+ case "nativeEvent":
631
+ used.add("addNativeEventListener");
632
+ return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
633
+ case "ref":
634
+ used.add("handleRef");
635
+ return `handleRef(${value}, ${ref});`;
636
+ case "use":
637
+ used.add("applyUse");
638
+ return `applyUse(${ref}, ${value});`;
639
+ }
640
+ }
520
641
  function staticAttrAssignment(el, prop) {
521
642
  const name = htmlAttrName(prop.name);
522
643
  const value = prop.literal;
@@ -567,6 +688,7 @@ function emitNode(node, used, templates) {
567
688
  `const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
568
689
  ];
569
690
  for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
691
+ for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
570
692
  for (const hole of plan.holes) {
571
693
  lines.push(
572
694
  `insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`