@fluixi/compiler 1.0.0-alpha.91 → 1.0.0-alpha.93
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/intrinsics.cjs +21 -1
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +20 -0
- package/dist/analyze/intrinsics.mjs +21 -1
- package/dist/analyze/reactive-bindings.cjs +21 -1
- package/dist/analyze/reactive-bindings.mjs +21 -1
- package/dist/analyze/static-graph.cjs +25 -5
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +6 -4
- package/dist/analyze/static-graph.mjs +25 -5
- package/dist/{babel-VBLQRHQ2.mjs → babel-RJHJQVEM.mjs} +4 -4
- package/dist/{chunk-D53J7ICY.mjs → chunk-56QSOVVL.mjs} +1 -1
- package/dist/{chunk-S4J4OCWK.mjs → chunk-OD53TMER.mjs} +22 -2
- package/dist/{chunk-TWDJUXWZ.mjs → chunk-R7PPFBCL.mjs} +1 -1
- package/dist/{chunk-QX6Y3OAR.mjs → chunk-TJIH7TLX.mjs} +1 -1
- package/dist/{chunk-3JWMCK4A.mjs → chunk-U7HCFLZ2.mjs} +153 -48
- package/dist/codegen/backends/imperative.cjs +27 -7
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +19 -4
- package/dist/codegen/backends/imperative.mjs +27 -7
- package/dist/frontend/babel/build-ir-lit.cjs +123 -44
- package/dist/frontend/babel/build-ir-lit.mjs +123 -44
- package/dist/frontend/babel/build-ir.cjs +123 -44
- package/dist/frontend/babel/build-ir.mjs +123 -44
- package/dist/frontend/babel/index.cjs +124 -45
- package/dist/frontend/babel/index.mjs +124 -45
- package/dist/frontend/babel/lower-template.cjs +123 -44
- package/dist/frontend/babel/lower-template.mjs +123 -44
- package/dist/frontend/babel/plugin.cjs +123 -44
- package/dist/frontend/babel/plugin.mjs +123 -44
- package/dist/index.cjs +86 -46
- package/dist/index.mjs +88 -48
- package/dist/integrations.cjs +246 -61
- package/dist/integrations.mjs +53 -19
- package/dist/lower/compile-template.cjs +44 -39
- package/dist/lower/compile-template.mjs +44 -39
- package/dist/lower/jsx.cjs +509 -6
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +114 -6
- package/dist/lower/jsx.mjs +509 -6
- package/dist/lower/template.cjs +43 -38
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +22 -30
- package/dist/lower/template.mjs +43 -38
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +33 -8
- package/dist/resolve/component-globals.d.cts +8 -0
- package/dist/resolve/component-globals.d.ts +8 -0
- package/dist/resolve/component-globals.d.ts.map +1 -1
- package/dist/resolve/component-globals.js +21 -12
- package/dist/resolve/component-globals.mjs +33 -8
- package/dist/resolve/write-globals.cjs +59 -8
- package/dist/resolve/write-globals.d.cts +6 -0
- package/dist/resolve/write-globals.d.ts +6 -0
- package/dist/resolve/write-globals.d.ts.map +1 -1
- package/dist/resolve/write-globals.js +35 -2
- package/dist/resolve/write-globals.mjs +61 -10
- package/dist/{server-fns-J56G3PFP.mjs → server-fns-ZFRDIQ2X.mjs} +4 -4
- package/dist/{server-functions-7PUFLRGF.mjs → server-functions-CTDXX67X.mjs} +3 -3
- package/dist/transform/index.cjs +199 -49
- package/dist/transform/index.mjs +199 -49
- package/dist/transform/intrinsics.cjs +47 -2
- package/dist/transform/intrinsics.d.cts +12 -0
- package/dist/transform/intrinsics.d.ts +12 -0
- package/dist/transform/intrinsics.d.ts.map +1 -1
- package/dist/transform/intrinsics.js +43 -1
- package/dist/transform/intrinsics.mjs +47 -2
- package/dist/transform/source-locations.cjs +67 -4
- package/dist/transform/source-locations.d.cts +7 -2
- package/dist/transform/source-locations.d.ts +7 -2
- package/dist/transform/source-locations.d.ts.map +1 -1
- package/dist/transform/source-locations.js +68 -3
- package/dist/transform/source-locations.mjs +67 -4
- package/dist/transform/templates.cjs +198 -48
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +5 -3
- package/dist/transform/templates.mjs +198 -48
- package/dist/{transform-D536WXGM.mjs → transform-QWWQDCXE.mjs} +33 -8
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -3
package/dist/transform/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -489,6 +489,7 @@ var INTRINSICS = {
|
|
|
489
489
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
490
490
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
491
491
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
492
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
492
493
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
493
494
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
494
495
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -498,7 +499,22 @@ var INTRINSICS = {
|
|
|
498
499
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
499
500
|
// dependency analysis must not guess at.
|
|
500
501
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
501
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
502
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
503
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
504
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
505
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
506
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
507
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
508
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
509
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
510
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
511
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
512
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
513
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
514
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
515
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
516
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
517
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
502
518
|
};
|
|
503
519
|
var RUNTIME_PRIMITIVES = {
|
|
504
520
|
signal: "signal-handle",
|
|
@@ -509,8 +525,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
509
525
|
createMemo: "memo-accessor",
|
|
510
526
|
createEffect: "effect",
|
|
511
527
|
createRenderEffect: "effect",
|
|
528
|
+
renderEffect: "effect",
|
|
529
|
+
computed: "effect",
|
|
512
530
|
createStore: "reactive-object",
|
|
513
531
|
resource: "resource-handle",
|
|
532
|
+
cachedResource: "resource-handle",
|
|
514
533
|
createResource: "reactive-object",
|
|
515
534
|
createSelector: "memo-accessor",
|
|
516
535
|
createDeferred: "memo-accessor"
|
|
@@ -519,6 +538,7 @@ var PRIMITIVE_MODULES = [
|
|
|
519
538
|
"@fluixi/reactive",
|
|
520
539
|
"@fluixi/reactive/signal",
|
|
521
540
|
"@fluixi/reactive/store",
|
|
541
|
+
"@fluixi/reactive/cached-resource",
|
|
522
542
|
"@fluixi/core"
|
|
523
543
|
];
|
|
524
544
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -654,6 +674,7 @@ function resolveReactiveBindings(program) {
|
|
|
654
674
|
// src/transform/source-locations.ts
|
|
655
675
|
var SOURCE_MARKER = "__fx_source";
|
|
656
676
|
var COMPONENT_MARKER = "__fx_component";
|
|
677
|
+
var CLASS_MARKER = "__fx_class";
|
|
657
678
|
var HOLE_MARKER = "__fx_hole";
|
|
658
679
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
659
680
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -671,11 +692,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
671
692
|
"createStore",
|
|
672
693
|
"createResource"
|
|
673
694
|
]);
|
|
674
|
-
function
|
|
695
|
+
function mayHaveSourceMarks(code) {
|
|
675
696
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
676
697
|
if (code.includes(name)) return true;
|
|
677
698
|
}
|
|
678
|
-
|
|
699
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
700
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
679
701
|
}
|
|
680
702
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
681
703
|
"IfStatement",
|
|
@@ -694,6 +716,7 @@ function isLoneBranch(statement, parent) {
|
|
|
694
716
|
function isExport(node) {
|
|
695
717
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
696
718
|
}
|
|
719
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
697
720
|
function isStatement(node) {
|
|
698
721
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
699
722
|
}
|
|
@@ -714,6 +737,14 @@ function walk3(node, visit, stack = []) {
|
|
|
714
737
|
}
|
|
715
738
|
function nameFor(stack) {
|
|
716
739
|
const declarator = stack[stack.length - 1];
|
|
740
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
741
|
+
const key = declarator.key;
|
|
742
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
743
|
+
const name = key.name ?? key.id?.name;
|
|
744
|
+
return name;
|
|
745
|
+
}
|
|
746
|
+
return void 0;
|
|
747
|
+
}
|
|
717
748
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
718
749
|
const id = declarator.id;
|
|
719
750
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -762,6 +793,17 @@ function collectSourceEdits(program, filename) {
|
|
|
762
793
|
});
|
|
763
794
|
}
|
|
764
795
|
}
|
|
796
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
797
|
+
const at = node.loc?.start;
|
|
798
|
+
const body = node.body;
|
|
799
|
+
if (at && body) {
|
|
800
|
+
edits.push({
|
|
801
|
+
start: body.start + 1,
|
|
802
|
+
end: body.start + 1,
|
|
803
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
}
|
|
765
807
|
if (node.type !== "CallExpression") return;
|
|
766
808
|
const callee = node.callee;
|
|
767
809
|
if (callee?.type !== "Identifier") return;
|
|
@@ -771,6 +813,26 @@ function collectSourceEdits(program, filename) {
|
|
|
771
813
|
if (!intrinsic && !imported) return;
|
|
772
814
|
const position = node.loc?.start;
|
|
773
815
|
if (!position) return;
|
|
816
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
817
|
+
const up = stack[i];
|
|
818
|
+
if (isStatement(up)) break;
|
|
819
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
820
|
+
if (claimed.has(node.start)) return;
|
|
821
|
+
claimed.add(node.start);
|
|
822
|
+
const label2 = nameFor(stack);
|
|
823
|
+
const own = !up.static;
|
|
824
|
+
const args2 = [
|
|
825
|
+
JSON.stringify(filename),
|
|
826
|
+
String(position.line),
|
|
827
|
+
String(position.column),
|
|
828
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
829
|
+
own ? "this" : void 0
|
|
830
|
+
].filter((a) => a !== void 0).join(",");
|
|
831
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
832
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
774
836
|
let statement;
|
|
775
837
|
let parent;
|
|
776
838
|
let index = -1;
|
|
@@ -976,13 +1038,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
976
1038
|
used.add("createComponent");
|
|
977
1039
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
978
1040
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
979
|
-
const
|
|
980
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
981
|
-
);
|
|
1041
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
982
1042
|
if (children.length > 0) {
|
|
983
|
-
|
|
1043
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1044
|
+
}
|
|
1045
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1046
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1047
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
1048
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1049
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
984
1050
|
}
|
|
985
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
986
1051
|
if (spreads.length > 0) {
|
|
987
1052
|
used.add("mergeProps");
|
|
988
1053
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1064,7 +1129,8 @@ function emitNode(node, used, templates) {
|
|
|
1064
1129
|
} else {
|
|
1065
1130
|
used.add("spread");
|
|
1066
1131
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1067
|
-
const
|
|
1132
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1133
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1068
1134
|
parts.push(
|
|
1069
1135
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1070
1136
|
);
|
|
@@ -1195,6 +1261,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
1195
1261
|
function escapeTemplate(s) {
|
|
1196
1262
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1197
1263
|
}
|
|
1264
|
+
var CONTAINER = "container";
|
|
1198
1265
|
function capitalize(s) {
|
|
1199
1266
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
1200
1267
|
}
|
|
@@ -1249,10 +1316,6 @@ var Lowerer = class {
|
|
|
1249
1316
|
if (hasElse) i = elseIdx;
|
|
1250
1317
|
continue;
|
|
1251
1318
|
}
|
|
1252
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1253
|
-
out.push(this.lowerEach(child));
|
|
1254
|
-
continue;
|
|
1255
|
-
}
|
|
1256
1319
|
}
|
|
1257
1320
|
const node = this.lowerNode(child);
|
|
1258
1321
|
if (node) out.push(node);
|
|
@@ -1294,13 +1357,16 @@ var Lowerer = class {
|
|
|
1294
1357
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1295
1358
|
return node;
|
|
1296
1359
|
}
|
|
1360
|
+
const each = this.lowerEach(el);
|
|
1361
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
1362
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1297
1363
|
const at = this.tagAt(el);
|
|
1298
1364
|
return {
|
|
1299
1365
|
kind: "element",
|
|
1300
1366
|
tag: el.tag,
|
|
1301
1367
|
svg: el.namespace === "svg",
|
|
1302
1368
|
props: this.lowerAttributes(el.attributes),
|
|
1303
|
-
children
|
|
1369
|
+
children,
|
|
1304
1370
|
static: false,
|
|
1305
1371
|
...at ? { at } : {}
|
|
1306
1372
|
};
|
|
@@ -1372,10 +1438,14 @@ var Lowerer = class {
|
|
|
1372
1438
|
const at = this.tagAt(el);
|
|
1373
1439
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1374
1440
|
}
|
|
1375
|
-
/**
|
|
1441
|
+
/**
|
|
1442
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
1443
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
1444
|
+
* it is. Null when the element has no `each`.
|
|
1445
|
+
*/
|
|
1376
1446
|
lowerEach(el) {
|
|
1377
1447
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1378
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
1448
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1379
1449
|
const each = this.hole(eachDir.hole);
|
|
1380
1450
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1381
1451
|
if (eachDir.key) {
|
|
@@ -1385,12 +1455,12 @@ var Lowerer = class {
|
|
|
1385
1455
|
const arrow = this.itemArrow(el);
|
|
1386
1456
|
let childrenCode;
|
|
1387
1457
|
if (arrow) {
|
|
1388
|
-
const
|
|
1389
|
-
|
|
1390
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
1458
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
1459
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1391
1460
|
} else {
|
|
1392
|
-
const
|
|
1393
|
-
|
|
1461
|
+
const content = this.lowerChildren(el.children);
|
|
1462
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
1463
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1394
1464
|
}
|
|
1395
1465
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1396
1466
|
const at = this.tagAt(el);
|
|
@@ -1407,25 +1477,6 @@ var Lowerer = class {
|
|
|
1407
1477
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1408
1478
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1409
1479
|
}
|
|
1410
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1411
|
-
rebuildWithChildren(el, children) {
|
|
1412
|
-
const props = this.lowerAttributes(
|
|
1413
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1414
|
-
);
|
|
1415
|
-
if (el.kind === "Element") {
|
|
1416
|
-
const at = this.tagAt(el);
|
|
1417
|
-
return {
|
|
1418
|
-
kind: "element",
|
|
1419
|
-
tag: el.tag,
|
|
1420
|
-
svg: el.namespace === "svg",
|
|
1421
|
-
props,
|
|
1422
|
-
children,
|
|
1423
|
-
static: false,
|
|
1424
|
-
...at ? { at } : {}
|
|
1425
|
-
};
|
|
1426
|
-
}
|
|
1427
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1428
|
-
}
|
|
1429
1480
|
// --- attributes ---------------------------------------------------------
|
|
1430
1481
|
lowerAttributes(attrs) {
|
|
1431
1482
|
const props = [];
|
|
@@ -1744,6 +1795,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
1744
1795
|
"mouseup"
|
|
1745
1796
|
]);
|
|
1746
1797
|
var isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
1798
|
+
var CONTAINER2 = "container";
|
|
1799
|
+
function directive(node, name) {
|
|
1800
|
+
if (node.type !== "JSXElement") return void 0;
|
|
1801
|
+
const opening = node.openingElement;
|
|
1802
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
1803
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
1804
|
+
}
|
|
1805
|
+
function directiveExpr(attr) {
|
|
1806
|
+
const v = attr.value;
|
|
1807
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
1808
|
+
}
|
|
1809
|
+
function emitIR(ir, ctx) {
|
|
1810
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
1811
|
+
for (const s of imports) ctx.used.add(s);
|
|
1812
|
+
return inlineTemplates(code, templates);
|
|
1813
|
+
}
|
|
1747
1814
|
var posOf = (node, ctx) => {
|
|
1748
1815
|
if (!ctx.sourceFile) return void 0;
|
|
1749
1816
|
const at = node.loc?.start;
|
|
@@ -1852,7 +1919,16 @@ function buildProps(attrs, ctx) {
|
|
|
1852
1919
|
}
|
|
1853
1920
|
function buildChildren(children, ctx) {
|
|
1854
1921
|
const out = [];
|
|
1855
|
-
for (
|
|
1922
|
+
for (let i = 0; i < children.length; i++) {
|
|
1923
|
+
const child = children[i];
|
|
1924
|
+
if (directive(child, "if")) {
|
|
1925
|
+
let next = i + 1;
|
|
1926
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
1927
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
1928
|
+
out.push(buildIf(child, fallback, ctx));
|
|
1929
|
+
if (fallback) i = next;
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1856
1932
|
if (child.type === "JSXText") {
|
|
1857
1933
|
const text = cleanTemplateText(child.value);
|
|
1858
1934
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1889,19 +1965,68 @@ function readLoad(attrs) {
|
|
|
1889
1965
|
}
|
|
1890
1966
|
return void 0;
|
|
1891
1967
|
}
|
|
1968
|
+
function buildIf(node, fallback, ctx) {
|
|
1969
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
1970
|
+
const props = [
|
|
1971
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
1972
|
+
];
|
|
1973
|
+
if (fallback) {
|
|
1974
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
1975
|
+
}
|
|
1976
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
1977
|
+
}
|
|
1978
|
+
function buildEach(node, ctx) {
|
|
1979
|
+
const attr = directive(node, "each");
|
|
1980
|
+
if (!attr) return null;
|
|
1981
|
+
const list = directiveExpr(attr);
|
|
1982
|
+
const props = [
|
|
1983
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
1984
|
+
];
|
|
1985
|
+
const key = directive(node, "key");
|
|
1986
|
+
if (key) {
|
|
1987
|
+
const keyExpr = directiveExpr(key);
|
|
1988
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
1989
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
1990
|
+
}
|
|
1991
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
1992
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
1993
|
+
let render;
|
|
1994
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
1995
|
+
const fn = ctx.code(only);
|
|
1996
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
1997
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
1998
|
+
} else {
|
|
1999
|
+
const built = buildChildren(node.children, ctx);
|
|
2000
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
2001
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
2002
|
+
}
|
|
2003
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
2004
|
+
}
|
|
2005
|
+
function buildElement(node, ctx, handled) {
|
|
2006
|
+
const skip = new Set(handled);
|
|
2007
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2008
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2009
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2010
|
+
);
|
|
2011
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2012
|
+
const each = buildEach(node, ctx);
|
|
2013
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2014
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2015
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2016
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props: buildProps(attributes, ctx), children, static: false, ...at ? { at } : {} };
|
|
2017
|
+
}
|
|
1892
2018
|
function buildNode(node, ctx) {
|
|
1893
2019
|
if (node.type === "JSXFragment") {
|
|
1894
2020
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1895
2021
|
}
|
|
2022
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
1896
2023
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2024
|
+
if (!component) return buildElement(node, ctx, []);
|
|
1897
2025
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
1898
2026
|
const children = buildChildren(node.children, ctx);
|
|
1899
2027
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1903
|
-
}
|
|
1904
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2028
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2029
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1905
2030
|
}
|
|
1906
2031
|
function buildJsxIR(node, ctx) {
|
|
1907
2032
|
const ir = buildNode(node, ctx);
|
|
@@ -2358,10 +2483,34 @@ function collectIntrinsicEdits(program) {
|
|
|
2358
2483
|
});
|
|
2359
2484
|
return { edits, diagnostics, imports };
|
|
2360
2485
|
}
|
|
2486
|
+
function avoidBindingClashes(program, result, bound) {
|
|
2487
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
2488
|
+
for (const stmt of program.body ?? []) {
|
|
2489
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
2490
|
+
const module2 = stmt.source.value;
|
|
2491
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
2492
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
2493
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
2494
|
+
if (imported === spec.local.name && result.imports.get(module2)?.has(imported)) {
|
|
2495
|
+
importedAsIs.add(imported);
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
2500
|
+
for (const names of result.imports.values()) {
|
|
2501
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
2502
|
+
}
|
|
2503
|
+
if (!aliases.size) return;
|
|
2504
|
+
for (const edit of result.edits) {
|
|
2505
|
+
const alias = aliases.get(edit.code);
|
|
2506
|
+
if (alias) edit.code = alias;
|
|
2507
|
+
}
|
|
2508
|
+
result.aliases = aliases;
|
|
2509
|
+
}
|
|
2361
2510
|
function intrinsicImports(result, bound) {
|
|
2362
2511
|
const lines = [];
|
|
2363
2512
|
for (const [module2, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
2364
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
2513
|
+
const wanted = [...names].filter((name) => result.aliases?.has(name) || !bound.has(name)).sort().map((name) => result.aliases?.has(name) ? `${name} as ${result.aliases.get(name)}` : name);
|
|
2365
2514
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module2)};`);
|
|
2366
2515
|
}
|
|
2367
2516
|
return lines.length ? `${lines.join("\n")}
|
|
@@ -2546,7 +2695,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2546
2695
|
const wantsJsx = format !== "lit";
|
|
2547
2696
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
2548
2697
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
2549
|
-
const wantsSources = options.sourceLocations === true &&
|
|
2698
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
2550
2699
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
2551
2700
|
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
|
|
2552
2701
|
const ast = (0, import_parser2.parse)(code, {
|
|
@@ -2561,6 +2710,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2561
2710
|
});
|
|
2562
2711
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
2563
2712
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
2713
|
+
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
2564
2714
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
2565
2715
|
const silent = found.length === 0 && props.edits.length === 0 && sources.edits.length === 0 && intrinsics.edits.length === 0 && intrinsics.diagnostics.length === 0 && props.diagnostics.length === 0;
|
|
2566
2716
|
if (silent) return null;
|