@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.
- package/dist/analyze/static-graph.cjs +1 -1
- package/dist/analyze/static-graph.mjs +1 -1
- package/dist/{babel-5SX36G76.mjs → babel-HJY4RVAV.mjs} +33 -20
- package/dist/{chunk-NWF66YTU.mjs → chunk-4XEOMQ57.mjs} +1 -1
- package/dist/{chunk-FMQPBKTW.mjs → chunk-JUFI6IR3.mjs} +1 -1
- package/dist/{chunk-NUET3BJB.mjs → chunk-LCQHL2VQ.mjs} +132 -10
- package/dist/{chunk-2O2YW5ZO.mjs → chunk-LGUZRHYN.mjs} +2 -2
- package/dist/{chunk-RBIYCE6M.mjs → chunk-TDN5MYWI.mjs} +1 -1
- package/dist/{chunk-ZDZKJQ5N.mjs → chunk-W7DYOMXJ.mjs} +2 -2
- package/dist/{chunk-DN33T5GJ.mjs → chunk-WHEDRMNR.mjs} +1 -1
- package/dist/codegen/backends/imperative.cjs +130 -8
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +62 -0
- package/dist/codegen/backends/imperative.mjs +130 -8
- package/dist/codegen/partial-template.cjs +80 -8
- package/dist/codegen/partial-template.d.cts +21 -4
- package/dist/codegen/partial-template.d.ts +21 -4
- package/dist/codegen/partial-template.d.ts.map +1 -1
- package/dist/codegen/partial-template.js +0 -0
- package/dist/codegen/partial-template.mjs +80 -8
- package/dist/codegen/serialize-static.cjs +1 -0
- package/dist/codegen/serialize-static.d.cts +8 -0
- package/dist/codegen/serialize-static.d.ts +8 -0
- package/dist/codegen/serialize-static.d.ts.map +1 -1
- package/dist/codegen/serialize-static.js +1 -1
- package/dist/codegen/serialize-static.mjs +1 -0
- package/dist/frontend/babel/build-ir-html.cjs +149 -21
- package/dist/frontend/babel/build-ir-html.d.cts +3 -1
- package/dist/frontend/babel/build-ir-html.d.ts +3 -1
- package/dist/frontend/babel/build-ir-html.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir-html.mjs +149 -21
- package/dist/frontend/babel/build-ir.cjs +149 -21
- package/dist/frontend/babel/build-ir.d.cts +11 -2
- package/dist/frontend/babel/build-ir.d.ts +11 -2
- package/dist/frontend/babel/build-ir.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir.js +15 -9
- package/dist/frontend/babel/build-ir.mjs +149 -21
- package/dist/frontend/babel/index.cjs +160 -25
- package/dist/frontend/babel/index.mjs +160 -25
- package/dist/frontend/babel/lower-template.cjs +149 -21
- package/dist/frontend/babel/lower-template.d.cts +2 -1
- package/dist/frontend/babel/lower-template.d.ts +2 -1
- package/dist/frontend/babel/lower-template.d.ts.map +1 -1
- package/dist/frontend/babel/lower-template.js +4 -4
- package/dist/frontend/babel/lower-template.mjs +149 -21
- package/dist/frontend/babel/plugin.cjs +158 -23
- package/dist/frontend/babel/plugin.js +9 -2
- package/dist/frontend/babel/plugin.mjs +158 -23
- package/dist/index.cjs +131 -9
- package/dist/index.mjs +131 -9
- package/dist/integrations.cjs +165 -33
- package/dist/integrations.mjs +11 -11
- package/dist/lower/compile-template.cjs +131 -9
- package/dist/lower/compile-template.mjs +131 -9
- package/dist/lower/jsx.cjs +130 -8
- package/dist/lower/jsx.mjs +130 -8
- package/dist/lower/template.cjs +130 -8
- package/dist/lower/template.mjs +130 -8
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/{server-fns-3Z3ZKJLB.mjs → server-fns-WZJK4BJE.mjs} +5 -5
- package/dist/{server-functions-DB7AHWE6.mjs → server-functions-4KTFFEO3.mjs} +3 -3
- package/dist/transform/index.cjs +135 -16
- package/dist/transform/index.mjs +135 -16
- package/dist/transform/templates.cjs +134 -15
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +4 -8
- package/dist/transform/templates.mjs +134 -15
- package/dist/{transform-VMK2URDB.mjs → transform-NO46NFQH.mjs} +11 -14
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -363,10 +363,64 @@ function isHole(node) {
|
|
|
363
363
|
function isTemplateChild(node) {
|
|
364
364
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
365
365
|
}
|
|
366
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
367
|
+
function disposition(prop) {
|
|
368
|
+
if (prop.kind === "spread") return null;
|
|
369
|
+
if (prop.name === "ref") return "ref";
|
|
370
|
+
if (prop.name === "use") return "use";
|
|
371
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
372
|
+
if (prop.kind === "prop") return "property";
|
|
373
|
+
if (prop.kind !== "attr") return null;
|
|
374
|
+
const name = prop.name;
|
|
375
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
376
|
+
if (name.startsWith("prop:")) return "property";
|
|
377
|
+
if (name.startsWith("attr:")) return "attr";
|
|
378
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
379
|
+
if (name === "className" || name === "class") {
|
|
380
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
381
|
+
}
|
|
382
|
+
if (name === "classList") {
|
|
383
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
384
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
385
|
+
}
|
|
386
|
+
if (name === "style") {
|
|
387
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
388
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
389
|
+
}
|
|
390
|
+
if (name.includes(":")) return null;
|
|
391
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
392
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
393
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
394
|
+
return "attr";
|
|
395
|
+
}
|
|
396
|
+
function effectiveProps(el) {
|
|
397
|
+
const order = [];
|
|
398
|
+
const byName = /* @__PURE__ */ new Map();
|
|
399
|
+
for (const prop of el.props) {
|
|
400
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
401
|
+
byName.set(prop.name, prop);
|
|
402
|
+
}
|
|
403
|
+
return order.map((name) => byName.get(name));
|
|
404
|
+
}
|
|
405
|
+
function propPlan(el) {
|
|
406
|
+
const custom = el.tag.includes("-");
|
|
407
|
+
const plan = { serialize: [], bindings: [] };
|
|
408
|
+
for (const prop of effectiveProps(el)) {
|
|
409
|
+
const kind = disposition(prop);
|
|
410
|
+
if (kind === null) return null;
|
|
411
|
+
if (kind === "serialize") {
|
|
412
|
+
plan.serialize.push(prop);
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (custom) return null;
|
|
416
|
+
plan.bindings.push({ prop, kind });
|
|
417
|
+
}
|
|
418
|
+
return plan;
|
|
419
|
+
}
|
|
366
420
|
function isTemplateElement(node) {
|
|
367
421
|
if (node.svg) return false;
|
|
368
422
|
if (isRawTextElement(node.tag)) return false;
|
|
369
|
-
if (!node
|
|
423
|
+
if (!propPlan(node)) return false;
|
|
370
424
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
371
425
|
}
|
|
372
426
|
function containsHole(node) {
|
|
@@ -374,6 +428,15 @@ function containsHole(node) {
|
|
|
374
428
|
const children = node.children;
|
|
375
429
|
return children ? children.some(containsHole) : false;
|
|
376
430
|
}
|
|
431
|
+
function containsBinding(node) {
|
|
432
|
+
if (node.kind !== "element") return false;
|
|
433
|
+
const plan = propPlan(node);
|
|
434
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
435
|
+
return node.children.some(containsBinding);
|
|
436
|
+
}
|
|
437
|
+
function interesting(node) {
|
|
438
|
+
return containsHole(node) || containsBinding(node);
|
|
439
|
+
}
|
|
377
440
|
function addressable(el) {
|
|
378
441
|
for (let i = 0; i < el.children.length; i++) {
|
|
379
442
|
const child = el.children[i];
|
|
@@ -387,9 +450,10 @@ function addressable(el) {
|
|
|
387
450
|
function planPartialTemplate(root) {
|
|
388
451
|
if (!isTemplateElement(root)) return null;
|
|
389
452
|
if (!addressable(root)) return null;
|
|
390
|
-
if (!root
|
|
453
|
+
if (!interesting(root)) return null;
|
|
391
454
|
const steps = [];
|
|
392
455
|
const holes = [];
|
|
456
|
+
const bindings = [];
|
|
393
457
|
let refCount = 0;
|
|
394
458
|
const declare2 = (expr) => {
|
|
395
459
|
const ref = `_n$${refCount++}`;
|
|
@@ -397,11 +461,17 @@ function planPartialTemplate(root) {
|
|
|
397
461
|
return ref;
|
|
398
462
|
};
|
|
399
463
|
walk2(root, "_el$");
|
|
400
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
464
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
401
465
|
function walk2(el, elementRef) {
|
|
466
|
+
const plan = propPlan(el);
|
|
467
|
+
if (plan) {
|
|
468
|
+
for (const binding of plan.bindings) {
|
|
469
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
470
|
+
}
|
|
471
|
+
}
|
|
402
472
|
let last = -1;
|
|
403
473
|
el.children.forEach((child, i) => {
|
|
404
|
-
if (
|
|
474
|
+
if (interesting(child)) last = i;
|
|
405
475
|
});
|
|
406
476
|
let previous = null;
|
|
407
477
|
for (let i = 0; i <= last; i++) {
|
|
@@ -415,19 +485,21 @@ function planPartialTemplate(root) {
|
|
|
415
485
|
continue;
|
|
416
486
|
}
|
|
417
487
|
const ref = declare2(expr);
|
|
418
|
-
if (child.kind === "element" &&
|
|
488
|
+
if (child.kind === "element" && interesting(child)) walk2(child, ref);
|
|
419
489
|
previous = ref;
|
|
420
490
|
}
|
|
421
491
|
}
|
|
422
492
|
}
|
|
423
493
|
function serializeWithMarkers(el) {
|
|
424
|
-
return serializeStatic(
|
|
494
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
425
495
|
}
|
|
426
|
-
function
|
|
496
|
+
function templateTree(el) {
|
|
497
|
+
const plan = propPlan(el);
|
|
427
498
|
return {
|
|
428
499
|
...el,
|
|
500
|
+
props: plan ? plan.serialize : [],
|
|
429
501
|
children: el.children.map(
|
|
430
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
502
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
431
503
|
)
|
|
432
504
|
};
|
|
433
505
|
}
|
|
@@ -700,6 +772,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
700
772
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
701
773
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
702
774
|
}
|
|
775
|
+
function bindingTarget(binding) {
|
|
776
|
+
const name = binding.prop.name;
|
|
777
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
778
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
779
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
780
|
+
return htmlAttrName(name);
|
|
781
|
+
}
|
|
782
|
+
function bindingStatement(binding, used) {
|
|
783
|
+
const { ref, prop, kind } = binding;
|
|
784
|
+
const value = propValue(prop);
|
|
785
|
+
switch (kind) {
|
|
786
|
+
case "class":
|
|
787
|
+
used.add("setClassName");
|
|
788
|
+
return `setClassName(${ref}, ${value});`;
|
|
789
|
+
case "classList":
|
|
790
|
+
used.add("setClassList");
|
|
791
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
792
|
+
case "classListDynamic":
|
|
793
|
+
used.add("setDynamicClassList");
|
|
794
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
795
|
+
case "style":
|
|
796
|
+
used.add("setStyle");
|
|
797
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
798
|
+
case "styleDynamic":
|
|
799
|
+
used.add("setDynamicStyle");
|
|
800
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
801
|
+
case "attr":
|
|
802
|
+
used.add("setDynamicAttribute");
|
|
803
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
804
|
+
case "property":
|
|
805
|
+
used.add("setDynamicProperty");
|
|
806
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
807
|
+
case "boolAttr":
|
|
808
|
+
used.add("setDynamicBoolAttribute");
|
|
809
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
810
|
+
case "event":
|
|
811
|
+
used.add("addDelegatedEventListener");
|
|
812
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
813
|
+
case "nativeEvent":
|
|
814
|
+
used.add("addNativeEventListener");
|
|
815
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
816
|
+
case "ref":
|
|
817
|
+
used.add("handleRef");
|
|
818
|
+
return `handleRef(${value}, ${ref});`;
|
|
819
|
+
case "use":
|
|
820
|
+
used.add("applyUse");
|
|
821
|
+
return `applyUse(${ref}, ${value});`;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
703
824
|
function staticAttrAssignment(el, prop) {
|
|
704
825
|
const name = htmlAttrName(prop.name);
|
|
705
826
|
const value = prop.literal;
|
|
@@ -750,6 +871,7 @@ function emitNode(node, used, templates) {
|
|
|
750
871
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
751
872
|
];
|
|
752
873
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
874
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
753
875
|
for (const hole of plan.holes) {
|
|
754
876
|
lines.push(
|
|
755
877
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
|
@@ -1551,16 +1673,16 @@ var generate = import_generator.default.default ?? import_generator.default;
|
|
|
1551
1673
|
function gen(node) {
|
|
1552
1674
|
return generate(node, { concise: true }).code;
|
|
1553
1675
|
}
|
|
1554
|
-
function bindHole(expr, used, onNested) {
|
|
1676
|
+
function bindHole(expr, used, onNested, emit) {
|
|
1555
1677
|
const hole = {
|
|
1556
|
-
code: genExpr(expr, used, onNested),
|
|
1678
|
+
code: genExpr(expr, used, onNested, emit),
|
|
1557
1679
|
reactive: isReactiveExpr(expr)
|
|
1558
1680
|
};
|
|
1559
1681
|
if (import_core.types.isArrowFunctionExpression(expr) && !import_core.types.isBlockStatement(expr.body)) {
|
|
1560
1682
|
const body = expr.body;
|
|
1561
1683
|
hole.arrow = {
|
|
1562
1684
|
params: expr.params.map((p) => gen(p)),
|
|
1563
|
-
body: genExpr(body, used, onNested),
|
|
1685
|
+
body: genExpr(body, used, onNested, emit),
|
|
1564
1686
|
bodyReactive: isReactiveExpr(body)
|
|
1565
1687
|
};
|
|
1566
1688
|
}
|
|
@@ -1569,7 +1691,7 @@ function bindHole(expr, used, onNested) {
|
|
|
1569
1691
|
}
|
|
1570
1692
|
function lowerHtmlTemplate(node, used, opts = {}) {
|
|
1571
1693
|
const quasi = node.quasi;
|
|
1572
|
-
const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
|
|
1694
|
+
const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested, opts.emit));
|
|
1573
1695
|
return lowerTemplate(buildPieces(quasi), holes, used, opts);
|
|
1574
1696
|
}
|
|
1575
1697
|
function buildPieces(quasi) {
|
|
@@ -2057,7 +2179,7 @@ var generate2 = import_generator2.default.default ?? import_generator2.default;
|
|
|
2057
2179
|
function gen2(node) {
|
|
2058
2180
|
return generate2(node, { concise: true }).code;
|
|
2059
2181
|
}
|
|
2060
|
-
function transformNestedJSX(node, used, onNested) {
|
|
2182
|
+
function transformNestedJSX(node, used, onNested, emit) {
|
|
2061
2183
|
const clone = import_core2.types.cloneNode(node, true);
|
|
2062
2184
|
const file = import_core2.types.file(import_core2.types.program([import_core2.types.expressionStatement(clone)]));
|
|
2063
2185
|
let changed = false;
|
|
@@ -2070,9 +2192,12 @@ function transformNestedJSX(node, used, onNested) {
|
|
|
2070
2192
|
(0, import_core2.traverse)(file, {
|
|
2071
2193
|
"JSXElement|JSXFragment"(path) {
|
|
2072
2194
|
const jsx = path.node;
|
|
2073
|
-
const nestedIR = buildIR(jsx, used, onNested);
|
|
2195
|
+
const nestedIR = buildIR(jsx, used, onNested, emit);
|
|
2074
2196
|
onNested?.(nestedIR);
|
|
2075
|
-
const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
|
|
2197
|
+
const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
|
|
2198
|
+
templateClone: emit?.templateClone,
|
|
2199
|
+
partialTemplates: emit?.partialTemplates ?? true
|
|
2200
|
+
});
|
|
2076
2201
|
emitInto(path, inlineTemplates(code, templates), imports);
|
|
2077
2202
|
},
|
|
2078
2203
|
// Nested html templates compose: ${cond ? html`...` : html`...`},
|
|
@@ -2080,26 +2205,29 @@ function transformNestedJSX(node, used, onNested) {
|
|
|
2080
2205
|
TaggedTemplateExpression(path) {
|
|
2081
2206
|
const tag = path.node.tag;
|
|
2082
2207
|
if (!import_core2.types.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
|
|
2083
|
-
const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested });
|
|
2208
|
+
const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested, emit });
|
|
2084
2209
|
onNested?.(ir);
|
|
2085
|
-
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
2210
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
2211
|
+
templateClone: emit?.templateClone,
|
|
2212
|
+
partialTemplates: emit?.partialTemplates ?? true
|
|
2213
|
+
});
|
|
2086
2214
|
emitInto(path, inlineTemplates(code, templates), imports);
|
|
2087
2215
|
}
|
|
2088
2216
|
});
|
|
2089
2217
|
return changed ? file.program.body[0].expression : node;
|
|
2090
2218
|
}
|
|
2091
|
-
function genExpr(node, used, onNested) {
|
|
2092
|
-
return gen2(transformNestedJSX(node, used, onNested));
|
|
2219
|
+
function genExpr(node, used, onNested, emit) {
|
|
2220
|
+
return gen2(transformNestedJSX(node, used, onNested, emit));
|
|
2093
2221
|
}
|
|
2094
2222
|
function isReactiveExpr(node) {
|
|
2095
2223
|
return isReactiveShape(shapeOf(node));
|
|
2096
2224
|
}
|
|
2097
|
-
function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
|
|
2225
|
+
function buildIR(node, used = /* @__PURE__ */ new Set(), onNested, emit) {
|
|
2098
2226
|
const ir = buildJsxIR(node, {
|
|
2099
2227
|
code: (n) => (
|
|
2100
2228
|
// A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
|
|
2101
2229
|
// through the nested-JSX compile: it only ever needs printing.
|
|
2102
|
-
n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested)
|
|
2230
|
+
n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested, emit)
|
|
2103
2231
|
),
|
|
2104
2232
|
used
|
|
2105
2233
|
});
|
|
@@ -2434,7 +2562,10 @@ function adoptTemplates(code, templates, state) {
|
|
|
2434
2562
|
}
|
|
2435
2563
|
function emitViaIR(node, state) {
|
|
2436
2564
|
const used = /* @__PURE__ */ new Set();
|
|
2437
|
-
const ir = buildIR(node, used, nestedHook(state)
|
|
2565
|
+
const ir = buildIR(node, used, nestedHook(state), {
|
|
2566
|
+
partialTemplates: state.partialTemplates,
|
|
2567
|
+
templateClone: state.templateClone
|
|
2568
|
+
});
|
|
2438
2569
|
resolveComponentSources(ir, {
|
|
2439
2570
|
resolver: state.componentResolver,
|
|
2440
2571
|
modules: {
|
|
@@ -2483,7 +2614,11 @@ function dedupeImports(imports) {
|
|
|
2483
2614
|
function emitHtmlViaIR(node, state) {
|
|
2484
2615
|
const used = /* @__PURE__ */ new Set();
|
|
2485
2616
|
const svg = import_core3.types.isIdentifier(node.tag) && node.tag.name === "svg";
|
|
2486
|
-
const ir = buildIRFromHtml(node, used, {
|
|
2617
|
+
const ir = buildIRFromHtml(node, used, {
|
|
2618
|
+
svg,
|
|
2619
|
+
onNested: nestedHook(state),
|
|
2620
|
+
emit: { partialTemplates: state.partialTemplates, templateClone: state.templateClone }
|
|
2621
|
+
});
|
|
2487
2622
|
resolveComponentSources(ir, {
|
|
2488
2623
|
resolver: state.componentResolver,
|
|
2489
2624
|
modules: {
|
|
@@ -323,7 +323,10 @@ function emitViaIR(node, state) {
|
|
|
323
323
|
// `used` collects runtime symbols emitted for JSX nested inside expressions
|
|
324
324
|
// (render-props, ternaries, fallback={<p/>}, ...) so we import them too.
|
|
325
325
|
const used = new Set();
|
|
326
|
-
const ir = buildIR(node, used, nestedHook(state)
|
|
326
|
+
const ir = buildIR(node, used, nestedHook(state), {
|
|
327
|
+
partialTemplates: state.partialTemplates,
|
|
328
|
+
templateClone: state.templateClone,
|
|
329
|
+
});
|
|
327
330
|
// The same passes the html path runs. Without them `codegen: 'ir'` silently skipped
|
|
328
331
|
// resolution entirely: a resolved tag compiled to a reference with no import.
|
|
329
332
|
resolveComponentSources(ir, {
|
|
@@ -386,7 +389,11 @@ function dedupeImports(imports) {
|
|
|
386
389
|
function emitHtmlViaIR(node, state) {
|
|
387
390
|
const used = new Set();
|
|
388
391
|
const svg = t.isIdentifier(node.tag) && node.tag.name === 'svg';
|
|
389
|
-
const ir = buildIRFromHtml(node, used, {
|
|
392
|
+
const ir = buildIRFromHtml(node, used, {
|
|
393
|
+
svg,
|
|
394
|
+
onNested: nestedHook(state),
|
|
395
|
+
emit: { partialTemplates: state.partialTemplates, templateClone: state.templateClone },
|
|
396
|
+
});
|
|
390
397
|
// Resolve pass: annotate each component reference with where it comes from, before
|
|
391
398
|
// codegen. Bindings are not checked here: Program.exit knows the whole file's scope
|
|
392
399
|
// and drops any injected import whose name turns out to be bound.
|
|
@@ -329,10 +329,64 @@ function isHole(node) {
|
|
|
329
329
|
function isTemplateChild(node) {
|
|
330
330
|
return node.kind === "text" || node.kind === "element" && isTemplateElement(node);
|
|
331
331
|
}
|
|
332
|
+
var PROPERTY_BINDS = /* @__PURE__ */ new Set(["indeterminate"]);
|
|
333
|
+
function disposition(prop) {
|
|
334
|
+
if (prop.kind === "spread") return null;
|
|
335
|
+
if (prop.name === "ref") return "ref";
|
|
336
|
+
if (prop.name === "use") return "use";
|
|
337
|
+
if (prop.kind === "event") return prop.event ? "event" : null;
|
|
338
|
+
if (prop.kind === "prop") return "property";
|
|
339
|
+
if (prop.kind !== "attr") return null;
|
|
340
|
+
const name = prop.name;
|
|
341
|
+
if (name.startsWith("on:")) return "nativeEvent";
|
|
342
|
+
if (name.startsWith("prop:")) return "property";
|
|
343
|
+
if (name.startsWith("attr:")) return "attr";
|
|
344
|
+
if (name.startsWith("bool:")) return "boolAttr";
|
|
345
|
+
if (name === "className" || name === "class") {
|
|
346
|
+
return isPlainLiteralAttr(prop) ? "serialize" : "class";
|
|
347
|
+
}
|
|
348
|
+
if (name === "classList") {
|
|
349
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
350
|
+
return prop.reactive ? "classListDynamic" : "classList";
|
|
351
|
+
}
|
|
352
|
+
if (name === "style") {
|
|
353
|
+
if (isPlainLiteralAttr(prop)) return "serialize";
|
|
354
|
+
return prop.reactive ? "styleDynamic" : "style";
|
|
355
|
+
}
|
|
356
|
+
if (name.includes(":")) return null;
|
|
357
|
+
if (PROPERTY_ONLY.has(name)) return null;
|
|
358
|
+
if (PROPERTY_BINDS.has(name)) return "property";
|
|
359
|
+
if (prop.expr === void 0) return isPlainLiteralAttr(prop) ? "serialize" : null;
|
|
360
|
+
return "attr";
|
|
361
|
+
}
|
|
362
|
+
function effectiveProps(el) {
|
|
363
|
+
const order = [];
|
|
364
|
+
const byName = /* @__PURE__ */ new Map();
|
|
365
|
+
for (const prop of el.props) {
|
|
366
|
+
if (!byName.has(prop.name)) order.push(prop.name);
|
|
367
|
+
byName.set(prop.name, prop);
|
|
368
|
+
}
|
|
369
|
+
return order.map((name) => byName.get(name));
|
|
370
|
+
}
|
|
371
|
+
function propPlan(el) {
|
|
372
|
+
const custom = el.tag.includes("-");
|
|
373
|
+
const plan = { serialize: [], bindings: [] };
|
|
374
|
+
for (const prop of effectiveProps(el)) {
|
|
375
|
+
const kind = disposition(prop);
|
|
376
|
+
if (kind === null) return null;
|
|
377
|
+
if (kind === "serialize") {
|
|
378
|
+
plan.serialize.push(prop);
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
if (custom) return null;
|
|
382
|
+
plan.bindings.push({ prop, kind });
|
|
383
|
+
}
|
|
384
|
+
return plan;
|
|
385
|
+
}
|
|
332
386
|
function isTemplateElement(node) {
|
|
333
387
|
if (node.svg) return false;
|
|
334
388
|
if (isRawTextElement(node.tag)) return false;
|
|
335
|
-
if (!node
|
|
389
|
+
if (!propPlan(node)) return false;
|
|
336
390
|
return node.children.every((c) => isTemplateChild(c) || isHole(c));
|
|
337
391
|
}
|
|
338
392
|
function containsHole(node) {
|
|
@@ -340,6 +394,15 @@ function containsHole(node) {
|
|
|
340
394
|
const children = node.children;
|
|
341
395
|
return children ? children.some(containsHole) : false;
|
|
342
396
|
}
|
|
397
|
+
function containsBinding(node) {
|
|
398
|
+
if (node.kind !== "element") return false;
|
|
399
|
+
const plan = propPlan(node);
|
|
400
|
+
if (plan && plan.bindings.length > 0) return true;
|
|
401
|
+
return node.children.some(containsBinding);
|
|
402
|
+
}
|
|
403
|
+
function interesting(node) {
|
|
404
|
+
return containsHole(node) || containsBinding(node);
|
|
405
|
+
}
|
|
343
406
|
function addressable(el) {
|
|
344
407
|
for (let i = 0; i < el.children.length; i++) {
|
|
345
408
|
const child = el.children[i];
|
|
@@ -353,9 +416,10 @@ function addressable(el) {
|
|
|
353
416
|
function planPartialTemplate(root) {
|
|
354
417
|
if (!isTemplateElement(root)) return null;
|
|
355
418
|
if (!addressable(root)) return null;
|
|
356
|
-
if (!root
|
|
419
|
+
if (!interesting(root)) return null;
|
|
357
420
|
const steps = [];
|
|
358
421
|
const holes = [];
|
|
422
|
+
const bindings = [];
|
|
359
423
|
let refCount = 0;
|
|
360
424
|
const declare2 = (expr) => {
|
|
361
425
|
const ref = `_n$${refCount++}`;
|
|
@@ -363,11 +427,17 @@ function planPartialTemplate(root) {
|
|
|
363
427
|
return ref;
|
|
364
428
|
};
|
|
365
429
|
walk2(root, "_el$");
|
|
366
|
-
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes };
|
|
430
|
+
return { html: serializeWithMarkers(root), tag: root.tag, steps, holes, bindings };
|
|
367
431
|
function walk2(el, elementRef) {
|
|
432
|
+
const plan = propPlan(el);
|
|
433
|
+
if (plan) {
|
|
434
|
+
for (const binding of plan.bindings) {
|
|
435
|
+
bindings.push({ ref: elementRef, prop: binding.prop, kind: binding.kind });
|
|
436
|
+
}
|
|
437
|
+
}
|
|
368
438
|
let last = -1;
|
|
369
439
|
el.children.forEach((child, i) => {
|
|
370
|
-
if (
|
|
440
|
+
if (interesting(child)) last = i;
|
|
371
441
|
});
|
|
372
442
|
let previous = null;
|
|
373
443
|
for (let i = 0; i <= last; i++) {
|
|
@@ -381,19 +451,21 @@ function planPartialTemplate(root) {
|
|
|
381
451
|
continue;
|
|
382
452
|
}
|
|
383
453
|
const ref = declare2(expr);
|
|
384
|
-
if (child.kind === "element" &&
|
|
454
|
+
if (child.kind === "element" && interesting(child)) walk2(child, ref);
|
|
385
455
|
previous = ref;
|
|
386
456
|
}
|
|
387
457
|
}
|
|
388
458
|
}
|
|
389
459
|
function serializeWithMarkers(el) {
|
|
390
|
-
return serializeStatic(
|
|
460
|
+
return serializeStatic(templateTree(el)).split(SENTINEL).join(HOLE_START + HOLE_END);
|
|
391
461
|
}
|
|
392
|
-
function
|
|
462
|
+
function templateTree(el) {
|
|
463
|
+
const plan = propPlan(el);
|
|
393
464
|
return {
|
|
394
465
|
...el,
|
|
466
|
+
props: plan ? plan.serialize : [],
|
|
395
467
|
children: el.children.map(
|
|
396
|
-
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ?
|
|
468
|
+
(child) => isHole(child) ? { kind: "text", value: SENTINEL } : child.kind === "element" ? templateTree(child) : child
|
|
397
469
|
)
|
|
398
470
|
};
|
|
399
471
|
}
|
|
@@ -666,6 +738,55 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
666
738
|
const mark = at ? `globalThis.${SOURCE_MARKER}?.(${JSON.stringify(at.file)},${at.line},${at.column},${JSON.stringify(name)}), ` : "";
|
|
667
739
|
return `createMemo(${paren(`${mark}() => createComponent(${name}, ${obj})`, "value")})`;
|
|
668
740
|
}
|
|
741
|
+
function bindingTarget(binding) {
|
|
742
|
+
const name = binding.prop.name;
|
|
743
|
+
if (binding.kind === "boolAttr") return name.slice("bool:".length);
|
|
744
|
+
if (name.startsWith("prop:")) return name.slice("prop:".length);
|
|
745
|
+
if (name.startsWith("attr:")) return name.slice("attr:".length);
|
|
746
|
+
return htmlAttrName(name);
|
|
747
|
+
}
|
|
748
|
+
function bindingStatement(binding, used) {
|
|
749
|
+
const { ref, prop, kind } = binding;
|
|
750
|
+
const value = propValue(prop);
|
|
751
|
+
switch (kind) {
|
|
752
|
+
case "class":
|
|
753
|
+
used.add("setClassName");
|
|
754
|
+
return `setClassName(${ref}, ${value});`;
|
|
755
|
+
case "classList":
|
|
756
|
+
used.add("setClassList");
|
|
757
|
+
return `setClassList(${ref}, ${value}, []);`;
|
|
758
|
+
case "classListDynamic":
|
|
759
|
+
used.add("setDynamicClassList");
|
|
760
|
+
return `setDynamicClassList(${ref}, ${value});`;
|
|
761
|
+
case "style":
|
|
762
|
+
used.add("setStyle");
|
|
763
|
+
return `setStyle(${ref}, ${value}, []);`;
|
|
764
|
+
case "styleDynamic":
|
|
765
|
+
used.add("setDynamicStyle");
|
|
766
|
+
return `setDynamicStyle(${ref}, ${value});`;
|
|
767
|
+
case "attr":
|
|
768
|
+
used.add("setDynamicAttribute");
|
|
769
|
+
return `setDynamicAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
770
|
+
case "property":
|
|
771
|
+
used.add("setDynamicProperty");
|
|
772
|
+
return `setDynamicProperty(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
773
|
+
case "boolAttr":
|
|
774
|
+
used.add("setDynamicBoolAttribute");
|
|
775
|
+
return `setDynamicBoolAttribute(${ref}, ${JSON.stringify(bindingTarget(binding))}, ${value});`;
|
|
776
|
+
case "event":
|
|
777
|
+
used.add("addDelegatedEventListener");
|
|
778
|
+
return `addDelegatedEventListener(${ref}, ${JSON.stringify(prop.event.name)}, ${value});`;
|
|
779
|
+
case "nativeEvent":
|
|
780
|
+
used.add("addNativeEventListener");
|
|
781
|
+
return `addNativeEventListener(${ref}, ${JSON.stringify(prop.name.slice(3))}, ${value});`;
|
|
782
|
+
case "ref":
|
|
783
|
+
used.add("handleRef");
|
|
784
|
+
return `handleRef(${value}, ${ref});`;
|
|
785
|
+
case "use":
|
|
786
|
+
used.add("applyUse");
|
|
787
|
+
return `applyUse(${ref}, ${value});`;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
669
790
|
function staticAttrAssignment(el, prop) {
|
|
670
791
|
const name = htmlAttrName(prop.name);
|
|
671
792
|
const value = prop.literal;
|
|
@@ -716,6 +837,7 @@ function emitNode(node, used, templates) {
|
|
|
716
837
|
`const _el$ = templateNode(${id}, ${JSON.stringify(plan.tag)}, true${at ? `, false, ${JSON.stringify(at)}` : ""});`
|
|
717
838
|
];
|
|
718
839
|
for (const step of plan.steps) lines.push(`const ${step.ref} = ${step.expr};`);
|
|
840
|
+
for (const binding of plan.bindings) lines.push(bindingStatement(binding, used));
|
|
719
841
|
for (const hole of plan.holes) {
|
|
720
842
|
lines.push(
|
|
721
843
|
`insert(${hole.parentRef}, holeScope(${hole.startRef}, () => ${paren(emitNode(hole.node, used, templates), "arrowBody")}), ${hole.endRef}, holeContent(${hole.startRef}, ${hole.endRef}));`
|
|
@@ -1519,16 +1641,16 @@ var generate = _generate.default ?? _generate;
|
|
|
1519
1641
|
function gen(node) {
|
|
1520
1642
|
return generate(node, { concise: true }).code;
|
|
1521
1643
|
}
|
|
1522
|
-
function bindHole(expr, used, onNested) {
|
|
1644
|
+
function bindHole(expr, used, onNested, emit) {
|
|
1523
1645
|
const hole = {
|
|
1524
|
-
code: genExpr(expr, used, onNested),
|
|
1646
|
+
code: genExpr(expr, used, onNested, emit),
|
|
1525
1647
|
reactive: isReactiveExpr(expr)
|
|
1526
1648
|
};
|
|
1527
1649
|
if (t.isArrowFunctionExpression(expr) && !t.isBlockStatement(expr.body)) {
|
|
1528
1650
|
const body = expr.body;
|
|
1529
1651
|
hole.arrow = {
|
|
1530
1652
|
params: expr.params.map((p) => gen(p)),
|
|
1531
|
-
body: genExpr(body, used, onNested),
|
|
1653
|
+
body: genExpr(body, used, onNested, emit),
|
|
1532
1654
|
bodyReactive: isReactiveExpr(body)
|
|
1533
1655
|
};
|
|
1534
1656
|
}
|
|
@@ -1537,7 +1659,7 @@ function bindHole(expr, used, onNested) {
|
|
|
1537
1659
|
}
|
|
1538
1660
|
function lowerHtmlTemplate(node, used, opts = {}) {
|
|
1539
1661
|
const quasi = node.quasi;
|
|
1540
|
-
const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested));
|
|
1662
|
+
const holes = quasi.expressions.map((e) => bindHole(e, used, opts.onNested, opts.emit));
|
|
1541
1663
|
return lowerTemplate(buildPieces(quasi), holes, used, opts);
|
|
1542
1664
|
}
|
|
1543
1665
|
function buildPieces(quasi) {
|
|
@@ -2025,7 +2147,7 @@ var generate2 = _generate2.default ?? _generate2;
|
|
|
2025
2147
|
function gen2(node) {
|
|
2026
2148
|
return generate2(node, { concise: true }).code;
|
|
2027
2149
|
}
|
|
2028
|
-
function transformNestedJSX(node, used, onNested) {
|
|
2150
|
+
function transformNestedJSX(node, used, onNested, emit) {
|
|
2029
2151
|
const clone = t2.cloneNode(node, true);
|
|
2030
2152
|
const file = t2.file(t2.program([t2.expressionStatement(clone)]));
|
|
2031
2153
|
let changed = false;
|
|
@@ -2038,9 +2160,12 @@ function transformNestedJSX(node, used, onNested) {
|
|
|
2038
2160
|
traverse(file, {
|
|
2039
2161
|
"JSXElement|JSXFragment"(path) {
|
|
2040
2162
|
const jsx = path.node;
|
|
2041
|
-
const nestedIR = buildIR(jsx, used, onNested);
|
|
2163
|
+
const nestedIR = buildIR(jsx, used, onNested, emit);
|
|
2042
2164
|
onNested?.(nestedIR);
|
|
2043
|
-
const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
|
|
2165
|
+
const { code, imports, templates } = imperativeBackend.emit(nestedIR, {
|
|
2166
|
+
templateClone: emit?.templateClone,
|
|
2167
|
+
partialTemplates: emit?.partialTemplates ?? true
|
|
2168
|
+
});
|
|
2044
2169
|
emitInto(path, inlineTemplates(code, templates), imports);
|
|
2045
2170
|
},
|
|
2046
2171
|
// Nested html templates compose: ${cond ? html`...` : html`...`},
|
|
@@ -2048,26 +2173,29 @@ function transformNestedJSX(node, used, onNested) {
|
|
|
2048
2173
|
TaggedTemplateExpression(path) {
|
|
2049
2174
|
const tag = path.node.tag;
|
|
2050
2175
|
if (!t2.isIdentifier(tag) || tag.name !== "html" && tag.name !== "svg") return;
|
|
2051
|
-
const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested });
|
|
2176
|
+
const ir = buildIRFromHtml(path.node, used, { svg: tag.name === "svg", onNested, emit });
|
|
2052
2177
|
onNested?.(ir);
|
|
2053
|
-
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
2178
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
2179
|
+
templateClone: emit?.templateClone,
|
|
2180
|
+
partialTemplates: emit?.partialTemplates ?? true
|
|
2181
|
+
});
|
|
2054
2182
|
emitInto(path, inlineTemplates(code, templates), imports);
|
|
2055
2183
|
}
|
|
2056
2184
|
});
|
|
2057
2185
|
return changed ? file.program.body[0].expression : node;
|
|
2058
2186
|
}
|
|
2059
|
-
function genExpr(node, used, onNested) {
|
|
2060
|
-
return gen2(transformNestedJSX(node, used, onNested));
|
|
2187
|
+
function genExpr(node, used, onNested, emit) {
|
|
2188
|
+
return gen2(transformNestedJSX(node, used, onNested, emit));
|
|
2061
2189
|
}
|
|
2062
2190
|
function isReactiveExpr(node) {
|
|
2063
2191
|
return isReactiveShape(shapeOf(node));
|
|
2064
2192
|
}
|
|
2065
|
-
function buildIR(node, used = /* @__PURE__ */ new Set(), onNested) {
|
|
2193
|
+
function buildIR(node, used = /* @__PURE__ */ new Set(), onNested, emit) {
|
|
2066
2194
|
const ir = buildJsxIR(node, {
|
|
2067
2195
|
code: (n) => (
|
|
2068
2196
|
// A member-expression tag (`<ns.Foo/>`) is not an Expression, so it cannot go
|
|
2069
2197
|
// through the nested-JSX compile: it only ever needs printing.
|
|
2070
|
-
n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested)
|
|
2198
|
+
n.type === "JSXMemberExpression" ? gen2(n) : genExpr(n, used, onNested, emit)
|
|
2071
2199
|
),
|
|
2072
2200
|
used
|
|
2073
2201
|
});
|
|
@@ -2402,7 +2530,10 @@ function adoptTemplates(code, templates, state) {
|
|
|
2402
2530
|
}
|
|
2403
2531
|
function emitViaIR(node, state) {
|
|
2404
2532
|
const used = /* @__PURE__ */ new Set();
|
|
2405
|
-
const ir = buildIR(node, used, nestedHook(state)
|
|
2533
|
+
const ir = buildIR(node, used, nestedHook(state), {
|
|
2534
|
+
partialTemplates: state.partialTemplates,
|
|
2535
|
+
templateClone: state.templateClone
|
|
2536
|
+
});
|
|
2406
2537
|
resolveComponentSources(ir, {
|
|
2407
2538
|
resolver: state.componentResolver,
|
|
2408
2539
|
modules: {
|
|
@@ -2451,7 +2582,11 @@ function dedupeImports(imports) {
|
|
|
2451
2582
|
function emitHtmlViaIR(node, state) {
|
|
2452
2583
|
const used = /* @__PURE__ */ new Set();
|
|
2453
2584
|
const svg = t3.isIdentifier(node.tag) && node.tag.name === "svg";
|
|
2454
|
-
const ir = buildIRFromHtml(node, used, {
|
|
2585
|
+
const ir = buildIRFromHtml(node, used, {
|
|
2586
|
+
svg,
|
|
2587
|
+
onNested: nestedHook(state),
|
|
2588
|
+
emit: { partialTemplates: state.partialTemplates, templateClone: state.templateClone }
|
|
2589
|
+
});
|
|
2455
2590
|
resolveComponentSources(ir, {
|
|
2456
2591
|
resolver: state.componentResolver,
|
|
2457
2592
|
modules: {
|