@fluixi/compiler 1.0.0-alpha.104 → 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-5SX36G76.mjs → babel-HJY4RVAV.mjs} +33 -20
  4. package/dist/{chunk-NWF66YTU.mjs → chunk-4XEOMQ57.mjs} +1 -1
  5. package/dist/{chunk-FMQPBKTW.mjs → chunk-JUFI6IR3.mjs} +1 -1
  6. package/dist/{chunk-NUET3BJB.mjs → chunk-LCQHL2VQ.mjs} +132 -10
  7. package/dist/{chunk-2O2YW5ZO.mjs → chunk-LGUZRHYN.mjs} +2 -2
  8. package/dist/{chunk-RBIYCE6M.mjs → chunk-TDN5MYWI.mjs} +1 -1
  9. package/dist/{chunk-ZDZKJQ5N.mjs → chunk-W7DYOMXJ.mjs} +2 -2
  10. package/dist/{chunk-DN33T5GJ.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-3Z3ZKJLB.mjs → server-fns-WZJK4BJE.mjs} +5 -5
  62. package/dist/{server-functions-DB7AHWE6.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-VMK2URDB.mjs → transform-NO46NFQH.mjs} +11 -14
  70. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  71. package/package.json +4 -4
@@ -77,10 +77,64 @@ function isHole(node) {
77
77
  function isTemplateChild(node) {
78
78
  return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
79
79
  }
80
+ var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
81
+ function disposition(prop) {
82
+ if (prop.kind === "spread") return null;
83
+ if (prop.name === "ref") return "ref";
84
+ if (prop.name === "use") return "use";
85
+ if (prop.kind === "event") return prop.event ? "event" : null;
86
+ if (prop.kind === "prop") return "property";
87
+ if (prop.kind !== "attr") return null;
88
+ const name = prop.name;
89
+ if (name.startsWith("on:")) return "nativeEvent";
90
+ if (name.startsWith("prop:")) return "property";
91
+ if (name.startsWith("attr:")) return "attr";
92
+ if (name.startsWith("bool:")) return "boolAttr";
93
+ if (name === "className" || name === "class") {
94
+ return isPlainLiteralAttr(prop) ? "serialize" : "class";
95
+ }
96
+ if (name === "classList") {
97
+ if (isPlainLiteralAttr(prop)) return "serialize";
98
+ return prop.reactive ? "classListDynamic" : "classList";
99
+ }
100
+ if (name === "style") {
101
+ if (isPlainLiteralAttr(prop)) return "serialize";
102
+ return prop.reactive ? "styleDynamic" : "style";
103
+ }
104
+ if (name.includes(":")) return null;
105
+ if (PROPERTY_ONLY.has(name)) return null;
106
+ if (PROPERTY_BINDS.has(name)) return "property";
107
+ if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
108
+ return "attr";
109
+ }
110
+ function effectiveProps(el) {
111
+ const order = [];
112
+ const byName = /* @__PURE__ */ new Map();
113
+ for (const prop of el.props) {
114
+ if (!byName.has(prop.name)) order.push(prop.name);
115
+ byName.set(prop.name, prop);
116
+ }
117
+ return order.map((name) => byName.get(name));
118
+ }
119
+ function propPlan(el) {
120
+ const custom = el.tag.includes("-");
121
+ const plan = { serialize: [], bindings: [] };
122
+ for (const prop of effectiveProps(el)) {
123
+ const kind = disposition(prop);
124
+ if (kind === null) return null;
125
+ if (kind === "serialize") {
126
+ plan.serialize.push(prop);
127
+ continue;
128
+ }
129
+ if (custom) return null;
130
+ plan.bindings.push({ prop, kind });
131
+ }
132
+ return plan;
133
+ }
80
134
  function isTemplateElement(node) {
81
135
  if (node.svg) return false;
82
136
  if (isRawTextElement(node.tag)) return false;
83
- if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
137
+ if (!propPlan(node)) return false;
84
138
  return node.children.every((c) => isTemplateChild(c) || isHole(c));
85
139
  }
86
140
  function containsHole(node) {
@@ -88,6 +142,15 @@ function containsHole(node) {
88
142
  const children = node.children;
89
143
  return children ? children.some(containsHole) : false;
90
144
  }
145
+ function containsBinding(node) {
146
+ if (node.kind !== "element") return false;
147
+ const plan = propPlan(node);
148
+ if (plan && plan.bindings.length > 0) return true;
149
+ return node.children.some(containsBinding);
150
+ }
151
+ function interesting(node) {
152
+ return containsHole(node) || containsBinding(node);
153
+ }
91
154
  function addressable(el) {
92
155
  for (let i = 0; i < el.children.length; i++) {
93
156
  const child = el.children[i];
@@ -101,9 +164,10 @@ function addressable(el) {
101
164
  function planPartialTemplate(root) {
102
165
  if (!isTemplateElement(root)) return null;
103
166
  if (!addressable(root)) return null;
104
- if (!root.children.some(containsHole)) return null;
167
+ if (!interesting(root)) return null;
105
168
  const steps = [];
106
169
  const holes = [];
170
+ const bindings = [];
107
171
  let refCount = 0;
108
172
  const declare = (expr) => {
109
173
  const ref = `_n$${refCount++}`;
@@ -111,11 +175,17 @@ function planPartialTemplate(root) {
111
175
  return ref;
112
176
  };
113
177
  walk(root, "_el$");
114
- return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
178
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
115
179
  function walk(el, elementRef) {
180
+ const plan = propPlan(el);
181
+ if (plan) {
182
+ for (const binding of plan.bindings) {
183
+ bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
184
+ }
185
+ }
116
186
  let last = -1;
117
187
  el.children.forEach((child, i) => {
118
- if (containsHole(child)) last = i;
188
+ if (interesting(child)) last = i;
119
189
  });
120
190
  let previous = null;
121
191
  for (let i = 0; i <= last; i++) {
@@ -129,19 +199,21 @@ function planPartialTemplate(root) {
129
199
  continue;
130
200
  }
131
201
  const ref = declare(expr);
132
- if (child.kind === "element" && containsHole(child)) walk(child, ref);
202
+ if (child.kind === "element" && interesting(child)) walk(child, ref);
133
203
  previous = ref;
134
204
  }
135
205
  }
136
206
  }
137
207
  function serializeWithMarkers(el) {
138
- return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
208
+ return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
139
209
  }
140
- function withSentinels(el) {
210
+ function templateTree(el) {
211
+ const plan = propPlan(el);
141
212
  return {
142
213
  ...el,
214
+ props: plan ? plan.serialize : [],
143
215
  children: el.children.map(
144
- (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
216
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
145
217
  )
146
218
  };
147
219
  }
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/codegen/serialize-static.ts
21
21
  var serialize_static_exports = {};
22
22
  __export(serialize_static_exports, {
23
+ PROPERTY_ONLY: () => PROPERTY_ONLY,
23
24
  htmlAttrName: () => htmlAttrName,
24
25
  isPlainLiteralAttr: () => isPlainLiteralAttr,
25
26
  isRawTextElement: () => isRawTextElement,
@@ -7,6 +7,14 @@
7
7
  * guess, and anything it cannot represent is a bug in the analysis, not a fallback.
8
8
  */
9
9
  import type { IRElement, IRProp } from '../ir/nodes.cjs';
10
+ /**
11
+ * Names the runtime assigns as DOM properties, whatever they look like.
12
+ *
13
+ * `innerHTML="<b>x</b>"` in a template would be escaped into visible text, and `value`
14
+ * as an attribute sets the *default* value rather than the current one. Serializing any
15
+ * of these changes what the code means, so they stay on the imperative path.
16
+ */
17
+ export declare const PROPERTY_ONLY: Set<string>;
10
18
  /** True when this element's content must not be entity-escaped. */
11
19
  export declare function isRawTextElement(tag: string): boolean;
12
20
  /** The HTML spelling of an IR prop name. */
@@ -7,6 +7,14 @@
7
7
  * guess, and anything it cannot represent is a bug in the analysis, not a fallback.
8
8
  */
9
9
  import type { IRElement, IRProp } from '../ir/nodes.js';
10
+ /**
11
+ * Names the runtime assigns as DOM properties, whatever they look like.
12
+ *
13
+ * `innerHTML="<b>x</b>"` in a template would be escaped into visible text, and `value`
14
+ * as an attribute sets the *default* value rather than the current one. Serializing any
15
+ * of these changes what the code means, so they stay on the imperative path.
16
+ */
17
+ export declare const PROPERTY_ONLY: Set<string>;
10
18
  /** True when this element's content must not be entity-escaped. */
11
19
  export declare function isRawTextElement(tag: string): boolean;
12
20
  /** The HTML spelling of an IR prop name. */
@@ -1 +1 @@
1
- {"version":3,"file":"serialize-static.d.ts","sourceRoot":"","sources":["../../src/codegen/serialize-static.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAU,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA6DhE,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAgBvD;AAED,2BAA2B;AAC3B,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAKvD;AAmCD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAU9F"}
1
+ {"version":3,"file":"serialize-static.d.ts","sourceRoot":"","sources":["../../src/codegen/serialize-static.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAU,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA8BhE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,aAaxB,CAAC;AAWH,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAgBvD;AAED,2BAA2B;AAC3B,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAKvD;AAmCD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAU9F"}
@@ -31,7 +31,7 @@ const HTML_NAME = {
31
31
  * as an attribute sets the *default* value rather than the current one. Serializing any
32
32
  * of these changes what the code means, so they stay on the imperative path.
33
33
  */
34
- const PROPERTY_ONLY = new Set([
34
+ export const PROPERTY_ONLY = new Set([
35
35
  'innerHTML',
36
36
  'outerHTML',
37
37
  'innerText',
@@ -95,6 +95,7 @@ function templatePositions(root) {
95
95
  return file && pos.some((n) => n !== 0) ? { file, pos } : void 0;
96
96
  }
97
97
  export {
98
+ PROPERTY_ONLY,
98
99
  htmlAttrName,
99
100
  isPlainLiteralAttr,
100
101
  isRawTextElement,
@@ -196,10 +196,64 @@ function isHole(node) {
196
196
  function isTemplateChild(node) {
197
197
  return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
198
198
  }
199
+ var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
200
+ function disposition(prop) {
201
+ if (prop.kind === "spread") return null;
202
+ if (prop.name === "ref") return "ref";
203
+ if (prop.name === "use") return "use";
204
+ if (prop.kind === "event") return prop.event ? "event" : null;
205
+ if (prop.kind === "prop") return "property";
206
+ if (prop.kind !== "attr") return null;
207
+ const name = prop.name;
208
+ if (name.startsWith("on:")) return "nativeEvent";
209
+ if (name.startsWith("prop:")) return "property";
210
+ if (name.startsWith("attr:")) return "attr";
211
+ if (name.startsWith("bool:")) return "boolAttr";
212
+ if (name === "className" || name === "class") {
213
+ return isPlainLiteralAttr(prop) ? "serialize" : "class";
214
+ }
215
+ if (name === "classList") {
216
+ if (isPlainLiteralAttr(prop)) return "serialize";
217
+ return prop.reactive ? "classListDynamic" : "classList";
218
+ }
219
+ if (name === "style") {
220
+ if (isPlainLiteralAttr(prop)) return "serialize";
221
+ return prop.reactive ? "styleDynamic" : "style";
222
+ }
223
+ if (name.includes(":")) return null;
224
+ if (PROPERTY_ONLY.has(name)) return null;
225
+ if (PROPERTY_BINDS.has(name)) return "property";
226
+ if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
227
+ return "attr";
228
+ }
229
+ function effectiveProps(el) {
230
+ const order = [];
231
+ const byName = /* @__PURE__ */ new Map();
232
+ for (const prop of el.props) {
233
+ if (!byName.has(prop.name)) order.push(prop.name);
234
+ byName.set(prop.name, prop);
235
+ }
236
+ return order.map((name) => byName.get(name));
237
+ }
238
+ function propPlan(el) {
239
+ const custom = el.tag.includes("-");
240
+ const plan = { serialize: [], bindings: [] };
241
+ for (const prop of effectiveProps(el)) {
242
+ const kind = disposition(prop);
243
+ if (kind === null) return null;
244
+ if (kind === "serialize") {
245
+ plan.serialize.push(prop);
246
+ continue;
247
+ }
248
+ if (custom) return null;
249
+ plan.bindings.push({ prop, kind });
250
+ }
251
+ return plan;
252
+ }
199
253
  function isTemplateElement(node) {
200
254
  if (node.svg) return false;
201
255
  if (isRawTextElement(node.tag)) return false;
202
- if (!node.props.every((p) => isPlainLiteralAttr(p))) return false;
256
+ if (!propPlan(node)) return false;
203
257
  return node.children.every((c) => isTemplateChild(c) || isHole(c));
204
258
  }
205
259
  function containsHole(node) {
@@ -207,6 +261,15 @@ function containsHole(node) {
207
261
  const children = node.children;
208
262
  return children ? children.some(containsHole) : false;
209
263
  }
264
+ function containsBinding(node) {
265
+ if (node.kind !== "element") return false;
266
+ const plan = propPlan(node);
267
+ if (plan && plan.bindings.length > 0) return true;
268
+ return node.children.some(containsBinding);
269
+ }
270
+ function interesting(node) {
271
+ return containsHole(node) || containsBinding(node);
272
+ }
210
273
  function addressable(el) {
211
274
  for (let i = 0; i < el.children.length; i++) {
212
275
  const child = el.children[i];
@@ -220,9 +283,10 @@ function addressable(el) {
220
283
  function planPartialTemplate(root) {
221
284
  if (!isTemplateElement(root)) return null;
222
285
  if (!addressable(root)) return null;
223
- if (!root.children.some(containsHole)) return null;
286
+ if (!interesting(root)) return null;
224
287
  const steps = [];
225
288
  const holes = [];
289
+ const bindings = [];
226
290
  let refCount = 0;
227
291
  const declare = (expr) => {
228
292
  const ref = `_n$${refCount++}`;
@@ -230,11 +294,17 @@ function planPartialTemplate(root) {
230
294
  return ref;
231
295
  };
232
296
  walk(root, "_el$");
233
- return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
297
+ return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
234
298
  function walk(el, elementRef) {
299
+ const plan = propPlan(el);
300
+ if (plan) {
301
+ for (const binding of plan.bindings) {
302
+ bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
303
+ }
304
+ }
235
305
  let last = -1;
236
306
  el.children.forEach((child, i) => {
237
- if (containsHole(child)) last = i;
307
+ if (interesting(child)) last = i;
238
308
  });
239
309
  let previous = null;
240
310
  for (let i = 0; i <= last; i++) {
@@ -248,19 +318,21 @@ function planPartialTemplate(root) {
248
318
  continue;
249
319
  }
250
320
  const ref = declare(expr);
251
- if (child.kind === "element" && containsHole(child)) walk(child, ref);
321
+ if (child.kind === "element" && interesting(child)) walk(child, ref);
252
322
  previous = ref;
253
323
  }
254
324
  }
255
325
  }
256
326
  function serializeWithMarkers(el) {
257
- return serializeStatic(withSentinels(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
327
+ return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
258
328
  }
259
- function withSentinels(el) {
329
+ function templateTree(el) {
330
+ const plan = propPlan(el);
260
331
  return {
261
332
  ...el,
333
+ props: plan ? plan.serialize : [],
262
334
  children: el.children.map(
263
- (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? withSentinels(child) : child
335
+ (child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
264
336
  )
265
337
  };
266
338
  }
@@ -533,6 +605,55 @@ function emitComponent(name, props, children, used, templates, at) {
533
605
  const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
534
606
  return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
535
607
  }
608
+ function bindingTarget(binding) {
609
+ const name = binding.prop.name;
610
+ if (binding.kind === "boolAttr") return name.slice("bool:".length);
611
+ if (name.startsWith("prop:")) return name.slice("prop:".length);
612
+ if (name.startsWith("attr:")) return name.slice("attr:".length);
613
+ return htmlAttrName(name);
614
+ }
615
+ function bindingStatement(binding, used) {
616
+ const { ref, prop, kind } = binding;
617
+ const value = propValue(prop);
618
+ switch (kind) {
619
+ case "class":
620
+ used.add("setClassName");
621
+ return `setClassName(${ref}, ${value});`;
622
+ case "classList":
623
+ used.add("setClassList");
624
+ return `setClassList(${ref}, ${value}, []);`;
625
+ case "classListDynamic":
626
+ used.add("setDynamicClassList");
627
+ return `setDynamicClassList(${ref}, ${value});`;
628
+ case "style":
629
+ used.add("setStyle");
630
+ return `setStyle(${ref}, ${value}, []);`;
631
+ case "styleDynamic":
632
+ used.add("setDynamicStyle");
633
+ return `setDynamicStyle(${ref}, ${value});`;
634
+ case "attr":
635
+ used.add("setDynamicAttribute");
636
+ return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
637
+ case "property":
638
+ used.add("setDynamicProperty");
639
+ return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
640
+ case "boolAttr":
641
+ used.add("setDynamicBoolAttribute");
642
+ return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
643
+ case "event":
644
+ used.add("addDelegatedEventListener");
645
+ return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
646
+ case "nativeEvent":
647
+ used.add("addNativeEventListener");
648
+ return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
649
+ case "ref":
650
+ used.add("handleRef");
651
+ return `handleRef(${value}, ${ref});`;
652
+ case "use":
653
+ used.add("applyUse");
654
+ return `applyUse(${ref}, ${value});`;
655
+ }
656
+ }
536
657
  function staticAttrAssignment(el, prop) {
537
658
  const name = htmlAttrName(prop.name);
538
659
  const value = prop.literal;
@@ -583,6 +704,7 @@ function emitNode(node, used, templates) {
583
704
  `const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
584
705
  ];
585
706
  for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
707
+ for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
586
708
  for (const hole of plan.holes) {
587
709
  lines.push(
588
710
  `insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
@@ -1841,7 +1963,7 @@ var generate = import_generator.default.default ?? import_generator.default;
1841
1963
  function gen(node) {
1842
1964
  return generate(node, { concise: true }).code;
1843
1965
  }
1844
- function transformNestedJSX(node, used, onNested) {
1966
+ function transformNestedJSX(node, used, onNested, emit) {
1845
1967
  const clone = import_core.types.cloneNode(node, true);
1846
1968
  const file = import_core.types.file(import_core.types.program([import_core.types.expressionStatement(clone)]));
1847
1969
  let changed = false;
@@ -1854,9 +1976,12 @@ function transformNestedJSX(node, used, onNested) {
1854
1976
  (0, import_core.traverse)(file, {
1855
1977
  "JSXElement|JSXFragment"(path) {
1856
1978
  const jsx = path.node;
1857
- const nestedIR = buildIR(jsx, used, onNested);
1979
+ const nestedIR = buildIR(jsx, used, onNested, emit);
1858
1980
  onNested?.(nestedIR);
1859
- const { code, imports, templates } = imperativeBackend.emit(nestedIR, {});
1981
+ const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
1982
+ templateClone: emit?.templateClone,
1983
+ partialTemplates: emit?.partialTemplates ?? true
1984
+ });
1860
1985
  emitInto(path, inlineTemplates(code, templates), imports);
1861
1986
  },
1862
1987
  // Nested html templates compose: ${cond ? html`...` : html`...`},
@@ -1864,26 +1989,29 @@ function transformNestedJSX(node, used, onNested) {
1864
1989
  TaggedTemplateExpression(path) {
1865
1990
  const tag = path.node.tag;
1866
1991
  if (!import_core.types.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
1867
- const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested });
1992
+ const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested, emit });
1868
1993
  onNested?.(ir);
1869
- const { code, imports, templates } = imperativeBackend.emit(ir, {});
1994
+ const { code, imports, templates } = imperativeBackend.emit(ir, {
1995
+ templateClone: emit?.templateClone,
1996
+ partialTemplates: emit?.partialTemplates ?? true
1997
+ });
1870
1998
  emitInto(path, inlineTemplates(code, templates), imports);
1871
1999
  }
1872
2000
  });
1873
2001
  return changed ? file.program.body[0].expression : node;
1874
2002
  }
1875
- function genExpr(node, used, onNested) {
1876
- return gen(transformNestedJSX(node, used, onNested));
2003
+ function genExpr(node, used, onNested, emit) {
2004
+ return gen(transformNestedJSX(node, used, onNested, emit));
1877
2005
  }
1878
2006
  function isReactiveExpr(node) {
1879
2007
  return isReactiveShape(shapeOf(node));
1880
2008
  }
1881
- function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
2009
+ function buildIR(node, used = /* @__PURE__ */ new Set(), onNested, emit) {
1882
2010
  const ir = buildJsxIR(node, {
1883
2011
  code: (n) => (
1884
2012
  // A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
1885
2013
  // through the nested-JSX compile: it only ever needs printing.
1886
- n.type === "JSXMemberExpression" ? gen(n) : genExpr(n, used, onNested)
2014
+ n.type === "JSXMemberExpression" ? gen(n) : genExpr(n, used, onNested, emit)
1887
2015
  ),
1888
2016
  used
1889
2017
  });
@@ -1895,16 +2023,16 @@ var generate2 = import_generator2.default.default ?? import_generator2.default;
1895
2023
  function gen2(node) {
1896
2024
  return generate2(node, { concise: true }).code;
1897
2025
  }
1898
- function bindHole(expr, used, onNested) {
2026
+ function bindHole(expr, used, onNested, emit) {
1899
2027
  const hole = {
1900
- code: genExpr(expr, used, onNested),
2028
+ code: genExpr(expr, used, onNested, emit),
1901
2029
  reactive: isReactiveExpr(expr)
1902
2030
  };
1903
2031
  if (import_core2.types.isArrowFunctionExpression(expr) && !import_core2.types.isBlockStatement(expr.body)) {
1904
2032
  const body = expr.body;
1905
2033
  hole.arrow = {
1906
2034
  params: expr.params.map((p) => gen2(p)),
1907
- body: genExpr(body, used, onNested),
2035
+ body: genExpr(body, used, onNested, emit),
1908
2036
  bodyReactive: isReactiveExpr(body)
1909
2037
  };
1910
2038
  }
@@ -1913,7 +2041,7 @@ function bindHole(expr, used, onNested) {
1913
2041
  }
1914
2042
  function lowerHtmlTemplate(node, used, opts = {}) {
1915
2043
  const quasi = node.quasi;
1916
- const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
2044
+ const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested, opts.emit));
1917
2045
  return lowerTemplate(buildPieces(quasi), holes, used, opts);
1918
2046
  }
1919
2047
  function buildPieces(quasi) {
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import type { types as t } from '@babel/core';
17
17
  import type { IRNode } from '../../ir/nodes.cjs';
18
+ import type { NestedEmitOptions, NestedHook } from './build-ir.cjs';
18
19
  /**
19
20
  * Build IR from an `` html`...` `` (or `` svg`...` ``) TaggedTemplateExpression.
20
21
  * `used` collects runtime symbols emitted for anything nested inside a hole.
@@ -22,5 +23,6 @@ import type { IRNode } from '../../ir/nodes.cjs';
22
23
  */
23
24
  export declare function buildIRFromHtml(node: t.TaggedTemplateExpression, used?: Set<string>, opts?: {
24
25
  svg?: boolean;
25
- onNested?: (ir: IRNode) => void;
26
+ onNested?: NestedHook;
27
+ emit?: NestedEmitOptions;
26
28
  }): IRNode;
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import type { types as t } from '@babel/core';
17
17
  import type { IRNode } from '../../ir/nodes.js';
18
+ import type { NestedEmitOptions, NestedHook } from './build-ir.js';
18
19
  /**
19
20
  * Build IR from an `` html`...` `` (or `` svg`...` ``) TaggedTemplateExpression.
20
21
  * `used` collects runtime symbols emitted for anything nested inside a hole.
@@ -22,6 +23,7 @@ import type { IRNode } from '../../ir/nodes.js';
22
23
  */
23
24
  export declare function buildIRFromHtml(node: t.TaggedTemplateExpression, used?: Set<string>, opts?: {
24
25
  svg?: boolean;
25
- onNested?: (ir: IRNode) => void;
26
+ onNested?: NestedHook;
27
+ emit?: NestedEmitOptions;
26
28
  }): IRNode;
27
29
  //# sourceMappingURL=build-ir-html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-ir-html.d.ts","sourceRoot":"","sources":["../../../src/frontend/babel/build-ir-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,CAAC,CAAC,wBAAwB,EAChC,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,EAC7B,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GAC5D,MAAM,CAKR"}
1
+ {"version":3,"file":"build-ir-html.d.ts","sourceRoot":"","sources":["../../../src/frontend/babel/build-ir-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEnE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,CAAC,CAAC,wBAAwB,EAChC,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,EAC7B,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;CAAO,GAC5E,MAAM,CAKR"}