@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/integrations.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;
|
|
@@ -156,6 +156,7 @@ var init_intrinsics = __esm({
|
|
|
156
156
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
157
157
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
158
158
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
159
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
159
160
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
160
161
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
161
162
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -165,7 +166,22 @@ var init_intrinsics = __esm({
|
|
|
165
166
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
166
167
|
// dependency analysis must not guess at.
|
|
167
168
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
168
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
169
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
170
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
171
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
172
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
173
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
174
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
175
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
176
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
177
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
178
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
179
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
180
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
181
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
182
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
183
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
184
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
169
185
|
};
|
|
170
186
|
RUNTIME_PRIMITIVES = {
|
|
171
187
|
signal: "signal-handle",
|
|
@@ -176,8 +192,11 @@ var init_intrinsics = __esm({
|
|
|
176
192
|
createMemo: "memo-accessor",
|
|
177
193
|
createEffect: "effect",
|
|
178
194
|
createRenderEffect: "effect",
|
|
195
|
+
renderEffect: "effect",
|
|
196
|
+
computed: "effect",
|
|
179
197
|
createStore: "reactive-object",
|
|
180
198
|
resource: "resource-handle",
|
|
199
|
+
cachedResource: "resource-handle",
|
|
181
200
|
createResource: "reactive-object",
|
|
182
201
|
createSelector: "memo-accessor",
|
|
183
202
|
createDeferred: "memo-accessor"
|
|
@@ -186,6 +205,7 @@ var init_intrinsics = __esm({
|
|
|
186
205
|
"@fluixi/reactive",
|
|
187
206
|
"@fluixi/reactive/signal",
|
|
188
207
|
"@fluixi/reactive/store",
|
|
208
|
+
"@fluixi/reactive/cached-resource",
|
|
189
209
|
"@fluixi/core"
|
|
190
210
|
];
|
|
191
211
|
INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -684,11 +704,12 @@ var init_reactive_bindings = __esm({
|
|
|
684
704
|
});
|
|
685
705
|
|
|
686
706
|
// src/transform/source-locations.ts
|
|
687
|
-
function
|
|
707
|
+
function mayHaveSourceMarks(code) {
|
|
688
708
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
689
709
|
if (code.includes(name)) return true;
|
|
690
710
|
}
|
|
691
|
-
|
|
711
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
712
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
692
713
|
}
|
|
693
714
|
function isLoneBranch(statement, parent) {
|
|
694
715
|
if (!parent || statement.type === "BlockStatement") return false;
|
|
@@ -717,6 +738,14 @@ function walk3(node, visit, stack = []) {
|
|
|
717
738
|
}
|
|
718
739
|
function nameFor(stack) {
|
|
719
740
|
const declarator = stack[stack.length - 1];
|
|
741
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
742
|
+
const key = declarator.key;
|
|
743
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
744
|
+
const name = key.name ?? key.id?.name;
|
|
745
|
+
return name;
|
|
746
|
+
}
|
|
747
|
+
return void 0;
|
|
748
|
+
}
|
|
720
749
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
721
750
|
const id = declarator.id;
|
|
722
751
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -765,6 +794,17 @@ function collectSourceEdits(program, filename) {
|
|
|
765
794
|
});
|
|
766
795
|
}
|
|
767
796
|
}
|
|
797
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
798
|
+
const at = node.loc?.start;
|
|
799
|
+
const body = node.body;
|
|
800
|
+
if (at && body) {
|
|
801
|
+
edits.push({
|
|
802
|
+
start: body.start + 1,
|
|
803
|
+
end: body.start + 1,
|
|
804
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
}
|
|
768
808
|
if (node.type !== "CallExpression") return;
|
|
769
809
|
const callee = node.callee;
|
|
770
810
|
if (callee?.type !== "Identifier") return;
|
|
@@ -774,6 +814,26 @@ function collectSourceEdits(program, filename) {
|
|
|
774
814
|
if (!intrinsic && !imported) return;
|
|
775
815
|
const position = node.loc?.start;
|
|
776
816
|
if (!position) return;
|
|
817
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
818
|
+
const up = stack[i];
|
|
819
|
+
if (isStatement(up)) break;
|
|
820
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
821
|
+
if (claimed.has(node.start)) return;
|
|
822
|
+
claimed.add(node.start);
|
|
823
|
+
const label2 = nameFor(stack);
|
|
824
|
+
const own = !up.static;
|
|
825
|
+
const args2 = [
|
|
826
|
+
JSON.stringify(filename),
|
|
827
|
+
String(position.line),
|
|
828
|
+
String(position.column),
|
|
829
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
830
|
+
own ? "this" : void 0
|
|
831
|
+
].filter((a) => a !== void 0).join(",");
|
|
832
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
833
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
777
837
|
let statement;
|
|
778
838
|
let parent;
|
|
779
839
|
let index = -1;
|
|
@@ -813,7 +873,7 @@ function collectSourceEdits(program, filename) {
|
|
|
813
873
|
});
|
|
814
874
|
return { edits, marked: edits.length };
|
|
815
875
|
}
|
|
816
|
-
var SOURCE_MARKER, COMPONENT_MARKER, HOLE_MARKER, markHole, PROPS_MARKER, markProps, RUNTIME_PRIMITIVES2, SINGLE_STATEMENT_PARENTS;
|
|
876
|
+
var SOURCE_MARKER, COMPONENT_MARKER, CLASS_MARKER, HOLE_MARKER, markHole, PROPS_MARKER, markProps, RUNTIME_PRIMITIVES2, SINGLE_STATEMENT_PARENTS, CLASS_FIELDS;
|
|
817
877
|
var init_source_locations = __esm({
|
|
818
878
|
"src/transform/source-locations.ts"() {
|
|
819
879
|
"use strict";
|
|
@@ -821,6 +881,7 @@ var init_source_locations = __esm({
|
|
|
821
881
|
init_reactive_bindings();
|
|
822
882
|
SOURCE_MARKER = "__fx_source";
|
|
823
883
|
COMPONENT_MARKER = "__fx_component";
|
|
884
|
+
CLASS_MARKER = "__fx_class";
|
|
824
885
|
HOLE_MARKER = "__fx_hole";
|
|
825
886
|
markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
826
887
|
PROPS_MARKER = "__fx_props";
|
|
@@ -848,6 +909,7 @@ var init_source_locations = __esm({
|
|
|
848
909
|
"LabeledStatement",
|
|
849
910
|
"WithStatement"
|
|
850
911
|
]);
|
|
912
|
+
CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
851
913
|
}
|
|
852
914
|
});
|
|
853
915
|
|
|
@@ -1011,13 +1073,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
1011
1073
|
used.add("createComponent");
|
|
1012
1074
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
1013
1075
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
1014
|
-
const
|
|
1015
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
1016
|
-
);
|
|
1076
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
1017
1077
|
if (children.length > 0) {
|
|
1018
|
-
|
|
1078
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1079
|
+
}
|
|
1080
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1081
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1082
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
1083
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1084
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
1019
1085
|
}
|
|
1020
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
1021
1086
|
if (spreads.length > 0) {
|
|
1022
1087
|
used.add("mergeProps");
|
|
1023
1088
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1098,7 +1163,8 @@ function emitNode(node, used, templates) {
|
|
|
1098
1163
|
} else {
|
|
1099
1164
|
used.add("spread");
|
|
1100
1165
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1101
|
-
const
|
|
1166
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1167
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1102
1168
|
parts.push(
|
|
1103
1169
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1104
1170
|
);
|
|
@@ -1189,7 +1255,7 @@ function lowerTemplate(pieces, holes, used, opts = {}) {
|
|
|
1189
1255
|
const { root } = (0, import_template_parser.parseTemplate)(pieces, { svg: opts.svg });
|
|
1190
1256
|
return new Lowerer(holes, used, opts.sourceFile, opts.positionAt).lowerRoot(root.children);
|
|
1191
1257
|
}
|
|
1192
|
-
var import_template_parser, DELEGATED, Lowerer;
|
|
1258
|
+
var import_template_parser, DELEGATED, CONTAINER, Lowerer;
|
|
1193
1259
|
var init_template = __esm({
|
|
1194
1260
|
"src/lower/template.ts"() {
|
|
1195
1261
|
"use strict";
|
|
@@ -1212,6 +1278,7 @@ var init_template = __esm({
|
|
|
1212
1278
|
"mousedown",
|
|
1213
1279
|
"mouseup"
|
|
1214
1280
|
]);
|
|
1281
|
+
CONTAINER = "container";
|
|
1215
1282
|
Lowerer = class {
|
|
1216
1283
|
constructor(holes, used, sourceFile, positionAt) {
|
|
1217
1284
|
this.holes = holes;
|
|
@@ -1263,10 +1330,6 @@ var init_template = __esm({
|
|
|
1263
1330
|
if (hasElse) i = elseIdx;
|
|
1264
1331
|
continue;
|
|
1265
1332
|
}
|
|
1266
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1267
|
-
out.push(this.lowerEach(child));
|
|
1268
|
-
continue;
|
|
1269
|
-
}
|
|
1270
1333
|
}
|
|
1271
1334
|
const node = this.lowerNode(child);
|
|
1272
1335
|
if (node) out.push(node);
|
|
@@ -1308,13 +1371,16 @@ var init_template = __esm({
|
|
|
1308
1371
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1309
1372
|
return node;
|
|
1310
1373
|
}
|
|
1374
|
+
const each = this.lowerEach(el);
|
|
1375
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
1376
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1311
1377
|
const at = this.tagAt(el);
|
|
1312
1378
|
return {
|
|
1313
1379
|
kind: "element",
|
|
1314
1380
|
tag: el.tag,
|
|
1315
1381
|
svg: el.namespace === "svg",
|
|
1316
1382
|
props: this.lowerAttributes(el.attributes),
|
|
1317
|
-
children
|
|
1383
|
+
children,
|
|
1318
1384
|
static: false,
|
|
1319
1385
|
...at ? { at } : {}
|
|
1320
1386
|
};
|
|
@@ -1386,10 +1452,14 @@ var init_template = __esm({
|
|
|
1386
1452
|
const at = this.tagAt(el);
|
|
1387
1453
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1388
1454
|
}
|
|
1389
|
-
/**
|
|
1455
|
+
/**
|
|
1456
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
1457
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
1458
|
+
* it is. Null when the element has no `each`.
|
|
1459
|
+
*/
|
|
1390
1460
|
lowerEach(el) {
|
|
1391
1461
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1392
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
1462
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1393
1463
|
const each = this.hole(eachDir.hole);
|
|
1394
1464
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1395
1465
|
if (eachDir.key) {
|
|
@@ -1399,12 +1469,12 @@ var init_template = __esm({
|
|
|
1399
1469
|
const arrow = this.itemArrow(el);
|
|
1400
1470
|
let childrenCode;
|
|
1401
1471
|
if (arrow) {
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1404
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
1472
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
1473
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1405
1474
|
} else {
|
|
1406
|
-
const
|
|
1407
|
-
|
|
1475
|
+
const content = this.lowerChildren(el.children);
|
|
1476
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
1477
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1408
1478
|
}
|
|
1409
1479
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1410
1480
|
const at = this.tagAt(el);
|
|
@@ -1421,25 +1491,6 @@ var init_template = __esm({
|
|
|
1421
1491
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1422
1492
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1423
1493
|
}
|
|
1424
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1425
|
-
rebuildWithChildren(el, children) {
|
|
1426
|
-
const props = this.lowerAttributes(
|
|
1427
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1428
|
-
);
|
|
1429
|
-
if (el.kind === "Element") {
|
|
1430
|
-
const at = this.tagAt(el);
|
|
1431
|
-
return {
|
|
1432
|
-
kind: "element",
|
|
1433
|
-
tag: el.tag,
|
|
1434
|
-
svg: el.namespace === "svg",
|
|
1435
|
-
props,
|
|
1436
|
-
children,
|
|
1437
|
-
static: false,
|
|
1438
|
-
...at ? { at } : {}
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1442
|
-
}
|
|
1443
1494
|
// --- attributes ---------------------------------------------------------
|
|
1444
1495
|
lowerAttributes(attrs) {
|
|
1445
1496
|
const props = [];
|
|
@@ -1853,6 +1904,21 @@ var init_expr_shape = __esm({
|
|
|
1853
1904
|
});
|
|
1854
1905
|
|
|
1855
1906
|
// src/lower/jsx.ts
|
|
1907
|
+
function directive(node, name) {
|
|
1908
|
+
if (node.type !== "JSXElement") return void 0;
|
|
1909
|
+
const opening = node.openingElement;
|
|
1910
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
1911
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
1912
|
+
}
|
|
1913
|
+
function directiveExpr(attr) {
|
|
1914
|
+
const v = attr.value;
|
|
1915
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
1916
|
+
}
|
|
1917
|
+
function emitIR(ir, ctx) {
|
|
1918
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
1919
|
+
for (const s of imports) ctx.used.add(s);
|
|
1920
|
+
return inlineTemplates(code, templates);
|
|
1921
|
+
}
|
|
1856
1922
|
function literalOf(node) {
|
|
1857
1923
|
if (node.type === "StringLiteral" || node.type === "NumericLiteral" || node.type === "BooleanLiteral") {
|
|
1858
1924
|
return node.value;
|
|
@@ -1955,7 +2021,16 @@ function buildProps(attrs, ctx) {
|
|
|
1955
2021
|
}
|
|
1956
2022
|
function buildChildren(children, ctx) {
|
|
1957
2023
|
const out = [];
|
|
1958
|
-
for (
|
|
2024
|
+
for (let i = 0; i < children.length; i++) {
|
|
2025
|
+
const child = children[i];
|
|
2026
|
+
if (directive(child, "if")) {
|
|
2027
|
+
let next = i + 1;
|
|
2028
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
2029
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
2030
|
+
out.push(buildIf(child, fallback, ctx));
|
|
2031
|
+
if (fallback) i = next;
|
|
2032
|
+
continue;
|
|
2033
|
+
}
|
|
1959
2034
|
if (child.type === "JSXText") {
|
|
1960
2035
|
const text = cleanTemplateText(child.value);
|
|
1961
2036
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1992,26 +2067,75 @@ function readLoad(attrs) {
|
|
|
1992
2067
|
}
|
|
1993
2068
|
return void 0;
|
|
1994
2069
|
}
|
|
2070
|
+
function buildIf(node, fallback, ctx) {
|
|
2071
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
2072
|
+
const props = [
|
|
2073
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
2074
|
+
];
|
|
2075
|
+
if (fallback) {
|
|
2076
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
2077
|
+
}
|
|
2078
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
2079
|
+
}
|
|
2080
|
+
function buildEach(node, ctx) {
|
|
2081
|
+
const attr = directive(node, "each");
|
|
2082
|
+
if (!attr) return null;
|
|
2083
|
+
const list = directiveExpr(attr);
|
|
2084
|
+
const props = [
|
|
2085
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
2086
|
+
];
|
|
2087
|
+
const key = directive(node, "key");
|
|
2088
|
+
if (key) {
|
|
2089
|
+
const keyExpr = directiveExpr(key);
|
|
2090
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
2091
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
2092
|
+
}
|
|
2093
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
2094
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
2095
|
+
let render;
|
|
2096
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
2097
|
+
const fn = ctx.code(only);
|
|
2098
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
2099
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
2100
|
+
} else {
|
|
2101
|
+
const built = buildChildren(node.children, ctx);
|
|
2102
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
2103
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
2104
|
+
}
|
|
2105
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
2106
|
+
}
|
|
2107
|
+
function buildElement(node, ctx, handled) {
|
|
2108
|
+
const skip = new Set(handled);
|
|
2109
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2110
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2111
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2112
|
+
);
|
|
2113
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2114
|
+
const each = buildEach(node, ctx);
|
|
2115
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2116
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2117
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2118
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props: buildProps(attributes, ctx), children, static: false, ...at ? { at } : {} };
|
|
2119
|
+
}
|
|
1995
2120
|
function buildNode(node, ctx) {
|
|
1996
2121
|
if (node.type === "JSXFragment") {
|
|
1997
2122
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1998
2123
|
}
|
|
2124
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
1999
2125
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2126
|
+
if (!component) return buildElement(node, ctx, []);
|
|
2000
2127
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
2001
2128
|
const children = buildChildren(node.children, ctx);
|
|
2002
2129
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
2006
|
-
}
|
|
2007
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2130
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2131
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
2008
2132
|
}
|
|
2009
2133
|
function buildJsxIR(node, ctx) {
|
|
2010
2134
|
const ir = buildNode(node, ctx);
|
|
2011
2135
|
analyzeStatic(ir);
|
|
2012
2136
|
return ir;
|
|
2013
2137
|
}
|
|
2014
|
-
var SVG_TAGS, EVENT_RE, DELEGATED2, isReactive, posOf, isString;
|
|
2138
|
+
var SVG_TAGS, EVENT_RE, DELEGATED2, isReactive, CONTAINER2, posOf, isString;
|
|
2015
2139
|
var init_jsx = __esm({
|
|
2016
2140
|
"src/lower/jsx.ts"() {
|
|
2017
2141
|
"use strict";
|
|
@@ -2021,6 +2145,7 @@ var init_jsx = __esm({
|
|
|
2021
2145
|
init_analyze_static();
|
|
2022
2146
|
init_text();
|
|
2023
2147
|
init_paren();
|
|
2148
|
+
init_imperative();
|
|
2024
2149
|
SVG_TAGS = /* @__PURE__ */ new Set([
|
|
2025
2150
|
"svg",
|
|
2026
2151
|
"path",
|
|
@@ -2051,6 +2176,7 @@ var init_jsx = __esm({
|
|
|
2051
2176
|
"mouseup"
|
|
2052
2177
|
]);
|
|
2053
2178
|
isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
2179
|
+
CONTAINER2 = "container";
|
|
2054
2180
|
posOf = (node, ctx) => {
|
|
2055
2181
|
if (!ctx.sourceFile) return void 0;
|
|
2056
2182
|
const at = node.loc?.start;
|
|
@@ -3171,10 +3297,34 @@ function collectIntrinsicEdits(program) {
|
|
|
3171
3297
|
});
|
|
3172
3298
|
return { edits, diagnostics, imports };
|
|
3173
3299
|
}
|
|
3300
|
+
function avoidBindingClashes(program, result, bound) {
|
|
3301
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
3302
|
+
for (const stmt of program.body ?? []) {
|
|
3303
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
3304
|
+
const module2 = stmt.source.value;
|
|
3305
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
3306
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
3307
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
3308
|
+
if (imported === spec.local.name && result.imports.get(module2)?.has(imported)) {
|
|
3309
|
+
importedAsIs.add(imported);
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
3314
|
+
for (const names of result.imports.values()) {
|
|
3315
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
3316
|
+
}
|
|
3317
|
+
if (!aliases.size) return;
|
|
3318
|
+
for (const edit of result.edits) {
|
|
3319
|
+
const alias = aliases.get(edit.code);
|
|
3320
|
+
if (alias) edit.code = alias;
|
|
3321
|
+
}
|
|
3322
|
+
result.aliases = aliases;
|
|
3323
|
+
}
|
|
3174
3324
|
function intrinsicImports(result, bound) {
|
|
3175
3325
|
const lines = [];
|
|
3176
3326
|
for (const [module2, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
3177
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
3327
|
+
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);
|
|
3178
3328
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module2)};`);
|
|
3179
3329
|
}
|
|
3180
3330
|
return lines.length ? `${lines.join("\n")}
|
|
@@ -3352,7 +3502,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3352
3502
|
const wantsJsx = format !== "lit";
|
|
3353
3503
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
3354
3504
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
3355
|
-
const wantsSources = options.sourceLocations === true &&
|
|
3505
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
3356
3506
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
3357
3507
|
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
|
|
3358
3508
|
const ast = (0, import_parser2.parse)(code, {
|
|
@@ -3367,6 +3517,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3367
3517
|
});
|
|
3368
3518
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
3369
3519
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
3520
|
+
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
3370
3521
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
3371
3522
|
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;
|
|
3372
3523
|
if (silent) return null;
|
|
@@ -3706,7 +3857,7 @@ var server_fns_exports = {};
|
|
|
3706
3857
|
__export(server_fns_exports, {
|
|
3707
3858
|
transformServerFns: () => transformServerFns
|
|
3708
3859
|
});
|
|
3709
|
-
function
|
|
3860
|
+
function directive2(node) {
|
|
3710
3861
|
if (!FUNCTION_TYPES.has(node.type)) return null;
|
|
3711
3862
|
const body = node.body;
|
|
3712
3863
|
if (!body || body.type !== "BlockStatement") return null;
|
|
@@ -3722,7 +3873,7 @@ function findServerFns(node, out) {
|
|
|
3722
3873
|
return;
|
|
3723
3874
|
}
|
|
3724
3875
|
if (typeof node.type === "string") {
|
|
3725
|
-
const found =
|
|
3876
|
+
const found = directive2(node);
|
|
3726
3877
|
if (found) {
|
|
3727
3878
|
out.push({ fn: node, directive: found });
|
|
3728
3879
|
return;
|
|
@@ -3839,7 +3990,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
3839
3990
|
builtins = true,
|
|
3840
3991
|
intrinsics = true,
|
|
3841
3992
|
generator = "@fluixi/compiler",
|
|
3842
|
-
specifier = (module2) => module2
|
|
3993
|
+
specifier = (module2) => module2,
|
|
3994
|
+
candidates = []
|
|
3843
3995
|
} = options;
|
|
3844
3996
|
const all = [...rules];
|
|
3845
3997
|
if (builtins) {
|
|
@@ -3851,7 +4003,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
3851
4003
|
const shadowedByDom = [];
|
|
3852
4004
|
const unavailable = [];
|
|
3853
4005
|
const resolved = /* @__PURE__ */ new Map();
|
|
3854
|
-
|
|
4006
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
4007
|
+
for (const name of [...names].sort()) {
|
|
3855
4008
|
const target = resolver.resolve(name);
|
|
3856
4009
|
if (!target) continue;
|
|
3857
4010
|
const pkg = packageOf(target.module);
|
|
@@ -3862,7 +4015,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
3862
4015
|
resolved.set(name, target);
|
|
3863
4016
|
}
|
|
3864
4017
|
}
|
|
3865
|
-
const
|
|
4018
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
4019
|
+
const pkg = packageOf(i.module);
|
|
4020
|
+
return !available || !pkg || available.has(pkg);
|
|
4021
|
+
}) : [];
|
|
4022
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
3866
4023
|
const modules = [
|
|
3867
4024
|
.../* @__PURE__ */ new Set([...declared2.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
3868
4025
|
].sort();
|
|
@@ -3882,15 +4039,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
3882
4039
|
return `// import { ${n} } from '${module2 ? specifier(module2) : ""}';
|
|
3883
4040
|
`;
|
|
3884
4041
|
}).join("") : "";
|
|
3885
|
-
const intrinsicLines =
|
|
4042
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
3886
4043
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
3887
|
-
)
|
|
4044
|
+
);
|
|
3888
4045
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
3889
|
-
const patternNote = patternRules
|
|
4046
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
4047
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
4048
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
4049
|
+
` : `//
|
|
3890
4050
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
3891
4051
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
3892
4052
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
3893
|
-
|
|
4053
|
+
`;
|
|
3894
4054
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
3895
4055
|
//
|
|
3896
4056
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -3947,6 +4107,30 @@ function projectDependencies(root) {
|
|
|
3947
4107
|
return void 0;
|
|
3948
4108
|
}
|
|
3949
4109
|
}
|
|
4110
|
+
function patternCandidates(rules, root) {
|
|
4111
|
+
const out = [];
|
|
4112
|
+
for (const rule of rules) {
|
|
4113
|
+
if (!("match" in rule) || !rule.module.startsWith("/")) continue;
|
|
4114
|
+
const dir = (0, import_node_path.dirname)(rule.module);
|
|
4115
|
+
const file = (0, import_node_path.basename)(rule.module);
|
|
4116
|
+
const group = file.match(/\$\d+/);
|
|
4117
|
+
if (dir.includes("$") || !group || file.indexOf("$", group.index + 1) !== -1) continue;
|
|
4118
|
+
const before = file.slice(0, group.index);
|
|
4119
|
+
const after = file.slice(group.index + group[0].length);
|
|
4120
|
+
let entries;
|
|
4121
|
+
try {
|
|
4122
|
+
entries = (0, import_node_fs.readdirSync)((0, import_node_path.resolve)(root, dir.slice(1)));
|
|
4123
|
+
} catch {
|
|
4124
|
+
continue;
|
|
4125
|
+
}
|
|
4126
|
+
for (const entry of entries) {
|
|
4127
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
4128
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
return out;
|
|
4133
|
+
}
|
|
3950
4134
|
function writeComponentGlobals(options, root) {
|
|
3951
4135
|
if (options.globals === false) return { status: "skipped", reason: "disabled" };
|
|
3952
4136
|
const rules = options.resolve ?? [];
|
|
@@ -3962,6 +4146,7 @@ function writeComponentGlobals(options, root) {
|
|
|
3962
4146
|
}
|
|
3963
4147
|
const { source, declared: declared2 } = componentGlobals(rules, {
|
|
3964
4148
|
available: projectDependencies(root),
|
|
4149
|
+
candidates: patternCandidates(rules, root),
|
|
3965
4150
|
specifier: (module2) => forTypeScript(module2, (0, import_node_path.dirname)(target), root)
|
|
3966
4151
|
});
|
|
3967
4152
|
if (existing === source) {
|