@fluixi/compiler 1.0.0-alpha.92 → 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 +18 -0
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +18 -0
- package/dist/analyze/intrinsics.mjs +18 -0
- package/dist/analyze/reactive-bindings.cjs +18 -0
- package/dist/analyze/reactive-bindings.mjs +18 -0
- package/dist/analyze/static-graph.cjs +22 -4
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +6 -4
- package/dist/analyze/static-graph.mjs +22 -4
- package/dist/{babel-GI375YZ2.mjs → babel-RJHJQVEM.mjs} +4 -4
- package/dist/{chunk-QZ4CJPYP.mjs → chunk-56QSOVVL.mjs} +1 -1
- package/dist/{chunk-XJ5H2MXY.mjs → chunk-OD53TMER.mjs} +19 -1
- package/dist/{chunk-DWNWN5RH.mjs → chunk-R7PPFBCL.mjs} +1 -1
- package/dist/{chunk-VOUI6XPV.mjs → chunk-TJIH7TLX.mjs} +1 -1
- package/dist/{chunk-VC6X44FS.mjs → chunk-U7HCFLZ2.mjs} +153 -48
- package/dist/codegen/backends/imperative.cjs +24 -6
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +19 -4
- package/dist/codegen/backends/imperative.mjs +24 -6
- package/dist/frontend/babel/build-ir-lit.cjs +120 -43
- package/dist/frontend/babel/build-ir-lit.mjs +120 -43
- package/dist/frontend/babel/build-ir.cjs +120 -43
- package/dist/frontend/babel/build-ir.mjs +120 -43
- package/dist/frontend/babel/index.cjs +121 -44
- package/dist/frontend/babel/index.mjs +121 -44
- package/dist/frontend/babel/lower-template.cjs +120 -43
- package/dist/frontend/babel/lower-template.mjs +120 -43
- package/dist/frontend/babel/plugin.cjs +120 -43
- package/dist/frontend/babel/plugin.mjs +120 -43
- package/dist/index.cjs +41 -38
- package/dist/index.mjs +41 -38
- package/dist/integrations.cjs +176 -52
- package/dist/integrations.mjs +8 -8
- package/dist/lower/compile-template.cjs +41 -38
- package/dist/lower/compile-template.mjs +41 -38
- 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 +40 -37
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +22 -30
- package/dist/lower/template.mjs +40 -37
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +14 -0
- package/dist/resolve/component-globals.mjs +14 -0
- package/dist/resolve/write-globals.cjs +14 -0
- package/dist/resolve/write-globals.mjs +14 -0
- package/dist/{server-fns-BBZRZUPP.mjs → server-fns-ZFRDIQ2X.mjs} +4 -4
- package/dist/{server-functions-VEGLIFCE.mjs → server-functions-CTDXX67X.mjs} +3 -3
- package/dist/transform/index.cjs +170 -47
- package/dist/transform/index.mjs +170 -47
- package/dist/transform/intrinsics.cjs +18 -0
- package/dist/transform/intrinsics.mjs +18 -0
- package/dist/transform/source-locations.cjs +64 -3
- 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 +64 -3
- package/dist/transform/templates.cjs +169 -46
- package/dist/transform/templates.js +2 -2
- package/dist/transform/templates.mjs +169 -46
- package/dist/{transform-UWZ7ZGJ2.mjs → transform-QWWQDCXE.mjs} +7 -7
- 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.
|
|
@@ -491,6 +492,19 @@ var INTRINSICS = {
|
|
|
491
492
|
// dependency analysis must not guess at.
|
|
492
493
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
493
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" },
|
|
494
508
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
495
509
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
496
510
|
};
|
|
@@ -503,8 +517,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
503
517
|
createMemo: "memo-accessor",
|
|
504
518
|
createEffect: "effect",
|
|
505
519
|
createRenderEffect: "effect",
|
|
520
|
+
renderEffect: "effect",
|
|
521
|
+
computed: "effect",
|
|
506
522
|
createStore: "reactive-object",
|
|
507
523
|
resource: "resource-handle",
|
|
524
|
+
cachedResource: "resource-handle",
|
|
508
525
|
createResource: "reactive-object",
|
|
509
526
|
createSelector: "memo-accessor",
|
|
510
527
|
createDeferred: "memo-accessor"
|
|
@@ -513,6 +530,7 @@ var PRIMITIVE_MODULES = [
|
|
|
513
530
|
"@fluixi/reactive",
|
|
514
531
|
"@fluixi/reactive/signal",
|
|
515
532
|
"@fluixi/reactive/store",
|
|
533
|
+
"@fluixi/reactive/cached-resource",
|
|
516
534
|
"@fluixi/core"
|
|
517
535
|
];
|
|
518
536
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -648,6 +666,7 @@ function resolveReactiveBindings(program) {
|
|
|
648
666
|
// src/transform/source-locations.ts
|
|
649
667
|
var SOURCE_MARKER = "__fx_source";
|
|
650
668
|
var COMPONENT_MARKER = "__fx_component";
|
|
669
|
+
var CLASS_MARKER = "__fx_class";
|
|
651
670
|
var HOLE_MARKER = "__fx_hole";
|
|
652
671
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
653
672
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -665,11 +684,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
665
684
|
"createStore",
|
|
666
685
|
"createResource"
|
|
667
686
|
]);
|
|
668
|
-
function
|
|
687
|
+
function mayHaveSourceMarks(code) {
|
|
669
688
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
670
689
|
if (code.includes(name)) return true;
|
|
671
690
|
}
|
|
672
|
-
|
|
691
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
692
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
673
693
|
}
|
|
674
694
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
675
695
|
"IfStatement",
|
|
@@ -688,6 +708,7 @@ function isLoneBranch(statement, parent) {
|
|
|
688
708
|
function isExport(node) {
|
|
689
709
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
690
710
|
}
|
|
711
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
691
712
|
function isStatement(node) {
|
|
692
713
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
693
714
|
}
|
|
@@ -708,6 +729,14 @@ function walk3(node, visit, stack = []) {
|
|
|
708
729
|
}
|
|
709
730
|
function nameFor(stack) {
|
|
710
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
|
+
}
|
|
711
740
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
712
741
|
const id = declarator.id;
|
|
713
742
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -756,6 +785,17 @@ function collectSourceEdits(program, filename) {
|
|
|
756
785
|
});
|
|
757
786
|
}
|
|
758
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
|
+
}
|
|
759
799
|
if (node.type !== "CallExpression") return;
|
|
760
800
|
const callee = node.callee;
|
|
761
801
|
if (callee?.type !== "Identifier") return;
|
|
@@ -765,6 +805,26 @@ function collectSourceEdits(program, filename) {
|
|
|
765
805
|
if (!intrinsic && !imported) return;
|
|
766
806
|
const position = node.loc?.start;
|
|
767
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
|
+
}
|
|
768
828
|
let statement;
|
|
769
829
|
let parent;
|
|
770
830
|
let index = -1;
|
|
@@ -970,13 +1030,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
970
1030
|
used.add("createComponent");
|
|
971
1031
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
972
1032
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
973
|
-
const
|
|
974
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
975
|
-
);
|
|
1033
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
976
1034
|
if (children.length > 0) {
|
|
977
|
-
|
|
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(", ")} })`;
|
|
978
1042
|
}
|
|
979
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
980
1043
|
if (spreads.length > 0) {
|
|
981
1044
|
used.add("mergeProps");
|
|
982
1045
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -1058,7 +1121,8 @@ function emitNode(node, used, templates) {
|
|
|
1058
1121
|
} else {
|
|
1059
1122
|
used.add("spread");
|
|
1060
1123
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
1061
|
-
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)}` : "";
|
|
1062
1126
|
parts.push(
|
|
1063
1127
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
1064
1128
|
);
|
|
@@ -1189,6 +1253,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
1189
1253
|
function escapeTemplate(s) {
|
|
1190
1254
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1191
1255
|
}
|
|
1256
|
+
var CONTAINER = "container";
|
|
1192
1257
|
function capitalize(s) {
|
|
1193
1258
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
1194
1259
|
}
|
|
@@ -1243,10 +1308,6 @@ var Lowerer = class {
|
|
|
1243
1308
|
if (hasElse) i = elseIdx;
|
|
1244
1309
|
continue;
|
|
1245
1310
|
}
|
|
1246
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
1247
|
-
out.push(this.lowerEach(child));
|
|
1248
|
-
continue;
|
|
1249
|
-
}
|
|
1250
1311
|
}
|
|
1251
1312
|
const node = this.lowerNode(child);
|
|
1252
1313
|
if (node) out.push(node);
|
|
@@ -1288,13 +1349,16 @@ var Lowerer = class {
|
|
|
1288
1349
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
1289
1350
|
return node;
|
|
1290
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 };
|
|
1291
1355
|
const at = this.tagAt(el);
|
|
1292
1356
|
return {
|
|
1293
1357
|
kind: "element",
|
|
1294
1358
|
tag: el.tag,
|
|
1295
1359
|
svg: el.namespace === "svg",
|
|
1296
1360
|
props: this.lowerAttributes(el.attributes),
|
|
1297
|
-
children
|
|
1361
|
+
children,
|
|
1298
1362
|
static: false,
|
|
1299
1363
|
...at ? { at } : {}
|
|
1300
1364
|
};
|
|
@@ -1366,10 +1430,14 @@ var Lowerer = class {
|
|
|
1366
1430
|
const at = this.tagAt(el);
|
|
1367
1431
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
1368
1432
|
}
|
|
1369
|
-
/**
|
|
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
|
+
*/
|
|
1370
1438
|
lowerEach(el) {
|
|
1371
1439
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
1372
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
1440
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
1373
1441
|
const each = this.hole(eachDir.hole);
|
|
1374
1442
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
1375
1443
|
if (eachDir.key) {
|
|
@@ -1379,12 +1447,12 @@ var Lowerer = class {
|
|
|
1379
1447
|
const arrow = this.itemArrow(el);
|
|
1380
1448
|
let childrenCode;
|
|
1381
1449
|
if (arrow) {
|
|
1382
|
-
const
|
|
1383
|
-
|
|
1384
|
-
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}`;
|
|
1385
1452
|
} else {
|
|
1386
|
-
const
|
|
1387
|
-
|
|
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")}`;
|
|
1388
1456
|
}
|
|
1389
1457
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
1390
1458
|
const at = this.tagAt(el);
|
|
@@ -1401,25 +1469,6 @@ var Lowerer = class {
|
|
|
1401
1469
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
1402
1470
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
1403
1471
|
}
|
|
1404
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
1405
|
-
rebuildWithChildren(el, children) {
|
|
1406
|
-
const props = this.lowerAttributes(
|
|
1407
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
1408
|
-
);
|
|
1409
|
-
if (el.kind === "Element") {
|
|
1410
|
-
const at = this.tagAt(el);
|
|
1411
|
-
return {
|
|
1412
|
-
kind: "element",
|
|
1413
|
-
tag: el.tag,
|
|
1414
|
-
svg: el.namespace === "svg",
|
|
1415
|
-
props,
|
|
1416
|
-
children,
|
|
1417
|
-
static: false,
|
|
1418
|
-
...at ? { at } : {}
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
return { kind: "component", name: el.tag, props, children };
|
|
1422
|
-
}
|
|
1423
1472
|
// --- attributes ---------------------------------------------------------
|
|
1424
1473
|
lowerAttributes(attrs) {
|
|
1425
1474
|
const props = [];
|
|
@@ -1738,6 +1787,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
1738
1787
|
"mouseup"
|
|
1739
1788
|
]);
|
|
1740
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
|
+
}
|
|
1741
1806
|
var posOf = (node, ctx) => {
|
|
1742
1807
|
if (!ctx.sourceFile) return void 0;
|
|
1743
1808
|
const at = node.loc?.start;
|
|
@@ -1846,7 +1911,16 @@ function buildProps(attrs, ctx) {
|
|
|
1846
1911
|
}
|
|
1847
1912
|
function buildChildren(children, ctx) {
|
|
1848
1913
|
const out = [];
|
|
1849
|
-
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
|
+
}
|
|
1850
1924
|
if (child.type === "JSXText") {
|
|
1851
1925
|
const text = cleanTemplateText(child.value);
|
|
1852
1926
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -1883,19 +1957,68 @@ function readLoad(attrs) {
|
|
|
1883
1957
|
}
|
|
1884
1958
|
return void 0;
|
|
1885
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
|
+
}
|
|
1886
2010
|
function buildNode(node, ctx) {
|
|
1887
2011
|
if (node.type === "JSXFragment") {
|
|
1888
2012
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
1889
2013
|
}
|
|
2014
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
1890
2015
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
2016
|
+
if (!component) return buildElement(node, ctx, []);
|
|
1891
2017
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
1892
2018
|
const children = buildChildren(node.children, ctx);
|
|
1893
2019
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
1897
|
-
}
|
|
1898
|
-
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 } : {} };
|
|
1899
2022
|
}
|
|
1900
2023
|
function buildJsxIR(node, ctx) {
|
|
1901
2024
|
const ir = buildNode(node, ctx);
|
|
@@ -2541,7 +2664,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2541
2664
|
const wantsJsx = format !== "lit";
|
|
2542
2665
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
2543
2666
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
2544
|
-
const wantsSources = options.sourceLocations === true &&
|
|
2667
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
2545
2668
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
2546
2669
|
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
|
|
2547
2670
|
const ast = (0, import_parser2.parse)(code, {
|
|
@@ -21,7 +21,7 @@ import { imperativeBackend } from '../codegen/backends/imperative.js';
|
|
|
21
21
|
import { moduleBindings } from './bindings.js';
|
|
22
22
|
import { collectPropsEdits } from './props.js';
|
|
23
23
|
import { avoidBindingClashes, collectIntrinsicEdits, intrinsicImports } from './intrinsics.js';
|
|
24
|
-
import { collectSourceEdits,
|
|
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);
|