@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
|
@@ -481,6 +481,7 @@ var INTRINSICS = {
|
|
|
481
481
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
482
482
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
483
483
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
484
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
484
485
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
485
486
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
486
487
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -490,7 +491,22 @@ var INTRINSICS = {
|
|
|
490
491
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
491
492
|
// dependency analysis must not guess at.
|
|
492
493
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
493
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
494
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
495
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
496
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
497
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
498
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
499
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
500
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
501
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
502
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
503
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
504
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
505
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
506
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
507
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
508
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
509
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
494
510
|
};
|
|
495
511
|
var RUNTIME_PRIMITIVES = {
|
|
496
512
|
signal: "signal-handle",
|
|
@@ -501,8 +517,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
501
517
|
createMemo: "memo-accessor",
|
|
502
518
|
createEffect: "effect",
|
|
503
519
|
createRenderEffect: "effect",
|
|
520
|
+
renderEffect: "effect",
|
|
521
|
+
computed: "effect",
|
|
504
522
|
createStore: "reactive-object",
|
|
505
523
|
resource: "resource-handle",
|
|
524
|
+
cachedResource: "resource-handle",
|
|
506
525
|
createResource: "reactive-object",
|
|
507
526
|
createSelector: "memo-accessor",
|
|
508
527
|
createDeferred: "memo-accessor"
|
|
@@ -511,6 +530,7 @@ var PRIMITIVE_MODULES = [
|
|
|
511
530
|
"@fluixi/reactive",
|
|
512
531
|
"@fluixi/reactive/signal",
|
|
513
532
|
"@fluixi/reactive/store",
|
|
533
|
+
"@fluixi/reactive/cached-resource",
|
|
514
534
|
"@fluixi/core"
|
|
515
535
|
];
|
|
516
536
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -646,6 +666,7 @@ function resolveReactiveBindings(program) {
|
|
|
646
666
|
// src/transform/source-locations.ts
|
|
647
667
|
var SOURCE_MARKER = "__fx_source";
|
|
648
668
|
var COMPONENT_MARKER = "__fx_component";
|
|
669
|
+
var CLASS_MARKER = "__fx_class";
|
|
649
670
|
var HOLE_MARKER = "__fx_hole";
|
|
650
671
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
651
672
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -663,11 +684,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
663
684
|
"createStore",
|
|
664
685
|
"createResource"
|
|
665
686
|
]);
|
|
666
|
-
function
|
|
687
|
+
function mayHaveSourceMarks(code) {
|
|
667
688
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
668
689
|
if (code.includes(name)) return true;
|
|
669
690
|
}
|
|
670
|
-
|
|
691
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
692
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
671
693
|
}
|
|
672
694
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
673
695
|
"IfStatement",
|
|
@@ -686,6 +708,7 @@ function isLoneBranch(statement, parent) {
|
|
|
686
708
|
function isExport(node) {
|
|
687
709
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
688
710
|
}
|
|
711
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
689
712
|
function isStatement(node) {
|
|
690
713
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
691
714
|
}
|
|
@@ -706,6 +729,14 @@ function walk3(node, visit, stack = []) {
|
|
|
706
729
|
}
|
|
707
730
|
function nameFor(stack) {
|
|
708
731
|
const declarator = stack[stack.length - 1];
|
|
732
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
733
|
+
const key = declarator.key;
|
|
734
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
735
|
+
const name = key.name ?? key.id?.name;
|
|
736
|
+
return name;
|
|
737
|
+
}
|
|
738
|
+
return void 0;
|
|
739
|
+
}
|
|
709
740
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
710
741
|
const id = declarator.id;
|
|
711
742
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -754,6 +785,17 @@ function collectSourceEdits(program, filename) {
|
|
|
754
785
|
});
|
|
755
786
|
}
|
|
756
787
|
}
|
|
788
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
789
|
+
const at = node.loc?.start;
|
|
790
|
+
const body = node.body;
|
|
791
|
+
if (at && body) {
|
|
792
|
+
edits.push({
|
|
793
|
+
start: body.start + 1,
|
|
794
|
+
end: body.start + 1,
|
|
795
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
}
|
|
757
799
|
if (node.type !== "CallExpression") return;
|
|
758
800
|
const callee = node.callee;
|
|
759
801
|
if (callee?.type !== "Identifier") return;
|
|
@@ -763,6 +805,26 @@ function collectSourceEdits(program, filename) {
|
|
|
763
805
|
if (!intrinsic && !imported) return;
|
|
764
806
|
const position = node.loc?.start;
|
|
765
807
|
if (!position) return;
|
|
808
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
809
|
+
const up = stack[i];
|
|
810
|
+
if (isStatement(up)) break;
|
|
811
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
812
|
+
if (claimed.has(node.start)) return;
|
|
813
|
+
claimed.add(node.start);
|
|
814
|
+
const label2 = nameFor(stack);
|
|
815
|
+
const own = !up.static;
|
|
816
|
+
const args2 = [
|
|
817
|
+
JSON.stringify(filename),
|
|
818
|
+
String(position.line),
|
|
819
|
+
String(position.column),
|
|
820
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
821
|
+
own ? "this" : void 0
|
|
822
|
+
].filter((a) => a !== void 0).join(",");
|
|
823
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
824
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
766
828
|
let statement;
|
|
767
829
|
let parent;
|
|
768
830
|
let index = -1;
|
|
@@ -968,13 +1030,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
968
1030
|
used.add("createComponent");
|
|
969
1031
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
970
1032
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
971
|
-
const
|
|
972
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
973
|
-
);
|
|
1033
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
974
1034
|
if (children.length > 0) {
|
|
975
|
-
|
|
1035
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
1036
|
+
}
|
|
1037
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
1038
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
1039
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
1040
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
1041
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
976
1042
|
}
|
|
977
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
978
1043
|
if (spreads.length > 0) {
|
|
979
1044
|
used.add("mergeProps");
|
|
980
1045
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1056,7 +1121,8 @@ function emitNode(node, used, templates) {
|
|
|
1056
1121
|
} else {
|
|
1057
1122
|
used.add("spread");
|
|
1058
1123
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1059
|
-
const
|
|
1124
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
1125
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
1060
1126
|
parts.push(
|
|
1061
1127
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1062
1128
|
);
|
|
@@ -1187,6 +1253,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
1187
1253
|
function escapeTemplate(s) {
|
|
1188
1254
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1189
1255
|
}
|
|
1256
|
+
var CONTAINER = "container";
|
|
1190
1257
|
function capitalize(s) {
|
|
1191
1258
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
1192
1259
|
}
|
|
@@ -1241,10 +1308,6 @@ var Lowerer = class {
|
|
|
1241
1308
|
if (hasElse) i = elseIdx;
|
|
1242
1309
|
continue;
|
|
1243
1310
|
}
|
|
1244
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1245
|
-
out.push(this.lowerEach(child));
|
|
1246
|
-
continue;
|
|
1247
|
-
}
|
|
1248
1311
|
}
|
|
1249
1312
|
const node = this.lowerNode(child);
|
|
1250
1313
|
if (node) out.push(node);
|
|
@@ -1286,13 +1349,16 @@ var Lowerer = class {
|
|
|
1286
1349
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1287
1350
|
return node;
|
|
1288
1351
|
}
|
|
1352
|
+
const each = this.lowerEach(el);
|
|
1353
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
1354
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
1289
1355
|
const at = this.tagAt(el);
|
|
1290
1356
|
return {
|
|
1291
1357
|
kind: "element",
|
|
1292
1358
|
tag: el.tag,
|
|
1293
1359
|
svg: el.namespace === "svg",
|
|
1294
1360
|
props: this.lowerAttributes(el.attributes),
|
|
1295
|
-
children
|
|
1361
|
+
children,
|
|
1296
1362
|
static: false,
|
|
1297
1363
|
...at ? { at } : {}
|
|
1298
1364
|
};
|
|
@@ -1364,10 +1430,14 @@ var Lowerer = class {
|
|
|
1364
1430
|
const at = this.tagAt(el);
|
|
1365
1431
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1366
1432
|
}
|
|
1367
|
-
/**
|
|
1433
|
+
/**
|
|
1434
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
1435
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
1436
|
+
* it is. Null when the element has no `each`.
|
|
1437
|
+
*/
|
|
1368
1438
|
lowerEach(el) {
|
|
1369
1439
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1370
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
1440
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1371
1441
|
const each = this.hole(eachDir.hole);
|
|
1372
1442
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1373
1443
|
if (eachDir.key) {
|
|
@@ -1377,12 +1447,12 @@ var Lowerer = class {
|
|
|
1377
1447
|
const arrow = this.itemArrow(el);
|
|
1378
1448
|
let childrenCode;
|
|
1379
1449
|
if (arrow) {
|
|
1380
|
-
const
|
|
1381
|
-
|
|
1382
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
1450
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
1451
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
1383
1452
|
} else {
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1453
|
+
const content = this.lowerChildren(el.children);
|
|
1454
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
1455
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
1386
1456
|
}
|
|
1387
1457
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1388
1458
|
const at = this.tagAt(el);
|
|
@@ -1399,25 +1469,6 @@ var Lowerer = class {
|
|
|
1399
1469
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1400
1470
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1401
1471
|
}
|
|
1402
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1403
|
-
rebuildWithChildren(el, children) {
|
|
1404
|
-
const props = this.lowerAttributes(
|
|
1405
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1406
|
-
);
|
|
1407
|
-
if (el.kind === "Element") {
|
|
1408
|
-
const at = this.tagAt(el);
|
|
1409
|
-
return {
|
|
1410
|
-
kind: "element",
|
|
1411
|
-
tag: el.tag,
|
|
1412
|
-
svg: el.namespace === "svg",
|
|
1413
|
-
props,
|
|
1414
|
-
children,
|
|
1415
|
-
static: false,
|
|
1416
|
-
...at ? { at } : {}
|
|
1417
|
-
};
|
|
1418
|
-
}
|
|
1419
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1420
|
-
}
|
|
1421
1472
|
// --- attributes ---------------------------------------------------------
|
|
1422
1473
|
lowerAttributes(attrs) {
|
|
1423
1474
|
const props = [];
|
|
@@ -1736,6 +1787,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
1736
1787
|
"mouseup"
|
|
1737
1788
|
]);
|
|
1738
1789
|
var isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
1790
|
+
var CONTAINER2 = "container";
|
|
1791
|
+
function directive(node, name) {
|
|
1792
|
+
if (node.type !== "JSXElement") return void 0;
|
|
1793
|
+
const opening = node.openingElement;
|
|
1794
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
1795
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
1796
|
+
}
|
|
1797
|
+
function directiveExpr(attr) {
|
|
1798
|
+
const v = attr.value;
|
|
1799
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
1800
|
+
}
|
|
1801
|
+
function emitIR(ir, ctx) {
|
|
1802
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
1803
|
+
for (const s of imports) ctx.used.add(s);
|
|
1804
|
+
return inlineTemplates(code, templates);
|
|
1805
|
+
}
|
|
1739
1806
|
var posOf = (node, ctx) => {
|
|
1740
1807
|
if (!ctx.sourceFile) return void 0;
|
|
1741
1808
|
const at = node.loc?.start;
|
|
@@ -1844,7 +1911,16 @@ function buildProps(attrs, ctx) {
|
|
|
1844
1911
|
}
|
|
1845
1912
|
function buildChildren(children, ctx) {
|
|
1846
1913
|
const out = [];
|
|
1847
|
-
for (
|
|
1914
|
+
for (let i = 0; i < children.length; i++) {
|
|
1915
|
+
const child = children[i];
|
|
1916
|
+
if (directive(child, "if")) {
|
|
1917
|
+
let next = i + 1;
|
|
1918
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
1919
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
1920
|
+
out.push(buildIf(child, fallback, ctx));
|
|
1921
|
+
if (fallback) i = next;
|
|
1922
|
+
continue;
|
|
1923
|
+
}
|
|
1848
1924
|
if (child.type === "JSXText") {
|
|
1849
1925
|
const text = cleanTemplateText(child.value);
|
|
1850
1926
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1881,19 +1957,68 @@ function readLoad(attrs) {
|
|
|
1881
1957
|
}
|
|
1882
1958
|
return void 0;
|
|
1883
1959
|
}
|
|
1960
|
+
function buildIf(node, fallback, ctx) {
|
|
1961
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
1962
|
+
const props = [
|
|
1963
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
1964
|
+
];
|
|
1965
|
+
if (fallback) {
|
|
1966
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
1967
|
+
}
|
|
1968
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
1969
|
+
}
|
|
1970
|
+
function buildEach(node, ctx) {
|
|
1971
|
+
const attr = directive(node, "each");
|
|
1972
|
+
if (!attr) return null;
|
|
1973
|
+
const list = directiveExpr(attr);
|
|
1974
|
+
const props = [
|
|
1975
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
1976
|
+
];
|
|
1977
|
+
const key = directive(node, "key");
|
|
1978
|
+
if (key) {
|
|
1979
|
+
const keyExpr = directiveExpr(key);
|
|
1980
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
1981
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
1982
|
+
}
|
|
1983
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
1984
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
1985
|
+
let render;
|
|
1986
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
1987
|
+
const fn = ctx.code(only);
|
|
1988
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
1989
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
1990
|
+
} else {
|
|
1991
|
+
const built = buildChildren(node.children, ctx);
|
|
1992
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
1993
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
1994
|
+
}
|
|
1995
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
1996
|
+
}
|
|
1997
|
+
function buildElement(node, ctx, handled) {
|
|
1998
|
+
const skip = new Set(handled);
|
|
1999
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
2000
|
+
const attributes = node.openingElement.attributes.filter(
|
|
2001
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
2002
|
+
);
|
|
2003
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
2004
|
+
const each = buildEach(node, ctx);
|
|
2005
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
2006
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2007
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2008
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props: buildProps(attributes, ctx), children, static: false, ...at ? { at } : {} };
|
|
2009
|
+
}
|
|
1884
2010
|
function buildNode(node, ctx) {
|
|
1885
2011
|
if (node.type === "JSXFragment") {
|
|
1886
2012
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1887
2013
|
}
|
|
2014
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
1888
2015
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2016
|
+
if (!component) return buildElement(node, ctx, []);
|
|
1889
2017
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
1890
2018
|
const children = buildChildren(node.children, ctx);
|
|
1891
2019
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1895
|
-
}
|
|
1896
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
2020
|
+
const load = readLoad(node.openingElement.attributes);
|
|
2021
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1897
2022
|
}
|
|
1898
2023
|
function buildJsxIR(node, ctx) {
|
|
1899
2024
|
const ir = buildNode(node, ctx);
|
|
@@ -2327,10 +2452,34 @@ function collectIntrinsicEdits(program) {
|
|
|
2327
2452
|
});
|
|
2328
2453
|
return { edits, diagnostics, imports };
|
|
2329
2454
|
}
|
|
2455
|
+
function avoidBindingClashes(program, result, bound) {
|
|
2456
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
2457
|
+
for (const stmt of program.body ?? []) {
|
|
2458
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
2459
|
+
const module2 = stmt.source.value;
|
|
2460
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
2461
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
2462
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
2463
|
+
if (imported === spec.local.name && result.imports.get(module2)?.has(imported)) {
|
|
2464
|
+
importedAsIs.add(imported);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
2469
|
+
for (const names of result.imports.values()) {
|
|
2470
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
2471
|
+
}
|
|
2472
|
+
if (!aliases.size) return;
|
|
2473
|
+
for (const edit of result.edits) {
|
|
2474
|
+
const alias = aliases.get(edit.code);
|
|
2475
|
+
if (alias) edit.code = alias;
|
|
2476
|
+
}
|
|
2477
|
+
result.aliases = aliases;
|
|
2478
|
+
}
|
|
2330
2479
|
function intrinsicImports(result, bound) {
|
|
2331
2480
|
const lines = [];
|
|
2332
2481
|
for (const [module2, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
2333
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
2482
|
+
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);
|
|
2334
2483
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module2)};`);
|
|
2335
2484
|
}
|
|
2336
2485
|
return lines.length ? `${lines.join("\n")}
|
|
@@ -2515,7 +2664,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2515
2664
|
const wantsJsx = format !== "lit";
|
|
2516
2665
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
2517
2666
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
2518
|
-
const wantsSources = options.sourceLocations === true &&
|
|
2667
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
2519
2668
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
2520
2669
|
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
|
|
2521
2670
|
const ast = (0, import_parser2.parse)(code, {
|
|
@@ -2530,6 +2679,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2530
2679
|
});
|
|
2531
2680
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
2532
2681
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
2682
|
+
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
2533
2683
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
2534
2684
|
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;
|
|
2535
2685
|
if (silent) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/transform/templates.ts"],"names":[],"mappings":"AASA,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAG1F,OAAO,KAAK,EAAqB,cAAc,EAAU,MAAM,gBAAgB,CAAC;AAWhF,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/transform/templates.ts"],"names":[],"mappings":"AASA,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAG1F,OAAO,KAAK,EAAqB,cAAc,EAAU,MAAM,gBAAgB,CAAC;AAWhF,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAgE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAoBzH,MAAM,WAAW,gBAAiB,SAAQ,sBAAsB;IAC9D;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAChC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5C,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,wEAAwE;IACxE,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC7C,8DAA8D;IAC9D,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,iFAAiF;IACjF,qBAAqB,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAChD;AAwTD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,gBAAqB,GAC7B,eAAe,GAAG,IAAI,CAkNxB"}
|
|
@@ -20,8 +20,8 @@ import { createComponentResolver } from '../resolve/component-resolver.js';
|
|
|
20
20
|
import { imperativeBackend } from '../codegen/backends/imperative.js';
|
|
21
21
|
import { moduleBindings } from './bindings.js';
|
|
22
22
|
import { collectPropsEdits } from './props.js';
|
|
23
|
-
import { collectIntrinsicEdits, intrinsicImports } from './intrinsics.js';
|
|
24
|
-
import { collectSourceEdits,
|
|
23
|
+
import { avoidBindingClashes, collectIntrinsicEdits, intrinsicImports } from './intrinsics.js';
|
|
24
|
+
import { collectSourceEdits, mayHaveSourceMarks } from './source-locations.js';
|
|
25
25
|
import { mayHaveIntrinsic } from '../analyze/intrinsics.js';
|
|
26
26
|
import { declaredNames } from '../analyze/reactive-bindings.js';
|
|
27
27
|
import { DOM_CONTROL_FLOW, CORE_CONTROL_FLOW, ROUTER_COMPONENTS } from '../resolve/builtins.js';
|
|
@@ -303,7 +303,7 @@ export function transformTemplates(code, id, options = {}) {
|
|
|
303
303
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
304
304
|
// A module can be nothing but reactive calls and still need marking, so the skip check
|
|
305
305
|
// has to look for those too when source locations are wanted.
|
|
306
|
-
const wantsSources = options.sourceLocations === true &&
|
|
306
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
307
307
|
// What a mark calls this file. The declaration marks and the usage marks are read back by
|
|
308
308
|
// name, so both passes have to spell it the same way.
|
|
309
309
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
@@ -331,6 +331,8 @@ export function transformTemplates(code, id, options = {}) {
|
|
|
331
331
|
const intrinsics = options.intrinsics === false
|
|
332
332
|
? { edits: [], diagnostics: [], imports: new Map() }
|
|
333
333
|
: collectIntrinsicEdits(ast.program);
|
|
334
|
+
if (intrinsics.edits.length)
|
|
335
|
+
avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
334
336
|
// Where each reactive primitive was created, for the devtools graph. Off unless asked
|
|
335
337
|
// for: it is development tooling, and production should carry none of it.
|
|
336
338
|
// `wantsSources` only decides whether a module with nothing else in it is worth parsing.
|