@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
package/dist/transform/index.mjs
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
|
|
|
3
3
|
// src/transform/templates.ts
|
|
4
4
|
import { parse as parse2 } from "@babel/parser";
|
|
@@ -1521,6 +1521,7 @@ var INTRINSICS = {
|
|
|
1521
1521
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
1522
1522
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
1523
1523
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
1524
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
1524
1525
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
1525
1526
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
1526
1527
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -1531,6 +1532,19 @@ var INTRINSICS = {
|
|
|
1531
1532
|
// dependency analysis must not guess at.
|
|
1532
1533
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
1533
1534
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
1535
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
1536
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
1537
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
1538
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
1539
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
1540
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
1541
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
1542
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
1543
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
1544
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
1545
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
1546
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
1547
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
1534
1548
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
1535
1549
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
1536
1550
|
};
|
|
@@ -1543,8 +1557,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
1543
1557
|
createMemo: "memo-accessor",
|
|
1544
1558
|
createEffect: "effect",
|
|
1545
1559
|
createRenderEffect: "effect",
|
|
1560
|
+
renderEffect: "effect",
|
|
1561
|
+
computed: "effect",
|
|
1546
1562
|
createStore: "reactive-object",
|
|
1547
1563
|
resource: "resource-handle",
|
|
1564
|
+
cachedResource: "resource-handle",
|
|
1548
1565
|
createResource: "reactive-object",
|
|
1549
1566
|
createSelector: "memo-accessor",
|
|
1550
1567
|
createDeferred: "memo-accessor"
|
|
@@ -1553,6 +1570,7 @@ var PRIMITIVE_MODULES = [
|
|
|
1553
1570
|
"@fluixi/reactive",
|
|
1554
1571
|
"@fluixi/reactive/signal",
|
|
1555
1572
|
"@fluixi/reactive/store",
|
|
1573
|
+
"@fluixi/reactive/cached-resource",
|
|
1556
1574
|
"@fluixi/core"
|
|
1557
1575
|
];
|
|
1558
1576
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n2) => n2.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -1688,6 +1706,7 @@ function resolveReactiveBindings(program) {
|
|
|
1688
1706
|
// src/transform/source-locations.ts
|
|
1689
1707
|
var SOURCE_MARKER = "__fx_source";
|
|
1690
1708
|
var COMPONENT_MARKER = "__fx_component";
|
|
1709
|
+
var CLASS_MARKER = "__fx_class";
|
|
1691
1710
|
var HOLE_MARKER = "__fx_hole";
|
|
1692
1711
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
1693
1712
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -1705,11 +1724,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
1705
1724
|
"createStore",
|
|
1706
1725
|
"createResource"
|
|
1707
1726
|
]);
|
|
1708
|
-
function
|
|
1727
|
+
function mayHaveSourceMarks(code) {
|
|
1709
1728
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
1710
1729
|
if (code.includes(name)) return true;
|
|
1711
1730
|
}
|
|
1712
|
-
|
|
1731
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
1732
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
1713
1733
|
}
|
|
1714
1734
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
1715
1735
|
"IfStatement",
|
|
@@ -1728,6 +1748,7 @@ function isLoneBranch(statement, parent) {
|
|
|
1728
1748
|
function isExport(node) {
|
|
1729
1749
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
1730
1750
|
}
|
|
1751
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
1731
1752
|
function isStatement(node) {
|
|
1732
1753
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
1733
1754
|
}
|
|
@@ -1748,6 +1769,14 @@ function walk3(node, visit, stack = []) {
|
|
|
1748
1769
|
}
|
|
1749
1770
|
function nameFor(stack) {
|
|
1750
1771
|
const declarator = stack[stack.length - 1];
|
|
1772
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
1773
|
+
const key = declarator.key;
|
|
1774
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
1775
|
+
const name = key.name ?? key.id?.name;
|
|
1776
|
+
return name;
|
|
1777
|
+
}
|
|
1778
|
+
return void 0;
|
|
1779
|
+
}
|
|
1751
1780
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
1752
1781
|
const id = declarator.id;
|
|
1753
1782
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -1796,6 +1825,17 @@ function collectSourceEdits(program, filename) {
|
|
|
1796
1825
|
});
|
|
1797
1826
|
}
|
|
1798
1827
|
}
|
|
1828
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
1829
|
+
const at = node.loc?.start;
|
|
1830
|
+
const body = node.body;
|
|
1831
|
+
if (at && body) {
|
|
1832
|
+
edits.push({
|
|
1833
|
+
start: body.start + 1,
|
|
1834
|
+
end: body.start + 1,
|
|
1835
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1799
1839
|
if (node.type !== "CallExpression") return;
|
|
1800
1840
|
const callee = node.callee;
|
|
1801
1841
|
if (callee?.type !== "Identifier") return;
|
|
@@ -1805,6 +1845,26 @@ function collectSourceEdits(program, filename) {
|
|
|
1805
1845
|
if (!intrinsic && !imported) return;
|
|
1806
1846
|
const position = node.loc?.start;
|
|
1807
1847
|
if (!position) return;
|
|
1848
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
1849
|
+
const up = stack[i];
|
|
1850
|
+
if (isStatement(up)) break;
|
|
1851
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
1852
|
+
if (claimed.has(node.start)) return;
|
|
1853
|
+
claimed.add(node.start);
|
|
1854
|
+
const label2 = nameFor(stack);
|
|
1855
|
+
const own = !up.static;
|
|
1856
|
+
const args2 = [
|
|
1857
|
+
JSON.stringify(filename),
|
|
1858
|
+
String(position.line),
|
|
1859
|
+
String(position.column),
|
|
1860
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
1861
|
+
own ? "this" : void 0
|
|
1862
|
+
].filter((a) => a !== void 0).join(",");
|
|
1863
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
1864
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1808
1868
|
let statement;
|
|
1809
1869
|
let parent;
|
|
1810
1870
|
let index = -1;
|
|
@@ -2010,13 +2070,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
2010
2070
|
used.add("createComponent");
|
|
2011
2071
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
2012
2072
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
2013
|
-
const
|
|
2014
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
2015
|
-
);
|
|
2073
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
2016
2074
|
if (children.length > 0) {
|
|
2017
|
-
|
|
2075
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
2076
|
+
}
|
|
2077
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
2078
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
2079
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
2080
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
2081
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
2018
2082
|
}
|
|
2019
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
2020
2083
|
if (spreads.length > 0) {
|
|
2021
2084
|
used.add("mergeProps");
|
|
2022
2085
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -2098,7 +2161,8 @@ function emitNode(node, used, templates) {
|
|
|
2098
2161
|
} else {
|
|
2099
2162
|
used.add("spread");
|
|
2100
2163
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
2101
|
-
const
|
|
2164
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
2165
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
2102
2166
|
parts.push(
|
|
2103
2167
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
2104
2168
|
);
|
|
@@ -2231,6 +2295,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
2231
2295
|
function escapeTemplate(s) {
|
|
2232
2296
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
2233
2297
|
}
|
|
2298
|
+
var CONTAINER = "container";
|
|
2234
2299
|
function capitalize(s) {
|
|
2235
2300
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
2236
2301
|
}
|
|
@@ -2285,10 +2350,6 @@ var Lowerer = class {
|
|
|
2285
2350
|
if (hasElse) i = elseIdx;
|
|
2286
2351
|
continue;
|
|
2287
2352
|
}
|
|
2288
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
2289
|
-
out.push(this.lowerEach(child));
|
|
2290
|
-
continue;
|
|
2291
|
-
}
|
|
2292
2353
|
}
|
|
2293
2354
|
const node = this.lowerNode(child);
|
|
2294
2355
|
if (node) out.push(node);
|
|
@@ -2330,13 +2391,16 @@ var Lowerer = class {
|
|
|
2330
2391
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
2331
2392
|
return node;
|
|
2332
2393
|
}
|
|
2394
|
+
const each = this.lowerEach(el);
|
|
2395
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
2396
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
2333
2397
|
const at = this.tagAt(el);
|
|
2334
2398
|
return {
|
|
2335
2399
|
kind: "element",
|
|
2336
2400
|
tag: el.tag,
|
|
2337
2401
|
svg: el.namespace === "svg",
|
|
2338
2402
|
props: this.lowerAttributes(el.attributes),
|
|
2339
|
-
children
|
|
2403
|
+
children,
|
|
2340
2404
|
static: false,
|
|
2341
2405
|
...at ? { at } : {}
|
|
2342
2406
|
};
|
|
@@ -2408,10 +2472,14 @@ var Lowerer = class {
|
|
|
2408
2472
|
const at = this.tagAt(el);
|
|
2409
2473
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
2410
2474
|
}
|
|
2411
|
-
/**
|
|
2475
|
+
/**
|
|
2476
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
2477
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
2478
|
+
* it is. Null when the element has no `each`.
|
|
2479
|
+
*/
|
|
2412
2480
|
lowerEach(el) {
|
|
2413
2481
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
2414
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
2482
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
2415
2483
|
const each = this.hole(eachDir.hole);
|
|
2416
2484
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
2417
2485
|
if (eachDir.key) {
|
|
@@ -2421,12 +2489,12 @@ var Lowerer = class {
|
|
|
2421
2489
|
const arrow = this.itemArrow(el);
|
|
2422
2490
|
let childrenCode;
|
|
2423
2491
|
if (arrow) {
|
|
2424
|
-
const
|
|
2425
|
-
|
|
2426
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
2492
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
2493
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
2427
2494
|
} else {
|
|
2428
|
-
const
|
|
2429
|
-
|
|
2495
|
+
const content = this.lowerChildren(el.children);
|
|
2496
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
2497
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
2430
2498
|
}
|
|
2431
2499
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
2432
2500
|
const at = this.tagAt(el);
|
|
@@ -2443,25 +2511,6 @@ var Lowerer = class {
|
|
|
2443
2511
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
2444
2512
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
2445
2513
|
}
|
|
2446
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
2447
|
-
rebuildWithChildren(el, children) {
|
|
2448
|
-
const props = this.lowerAttributes(
|
|
2449
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
2450
|
-
);
|
|
2451
|
-
if (el.kind === "Element") {
|
|
2452
|
-
const at = this.tagAt(el);
|
|
2453
|
-
return {
|
|
2454
|
-
kind: "element",
|
|
2455
|
-
tag: el.tag,
|
|
2456
|
-
svg: el.namespace === "svg",
|
|
2457
|
-
props,
|
|
2458
|
-
children,
|
|
2459
|
-
static: false,
|
|
2460
|
-
...at ? { at } : {}
|
|
2461
|
-
};
|
|
2462
|
-
}
|
|
2463
|
-
return { kind: "component", name: el.tag, props, children };
|
|
2464
|
-
}
|
|
2465
2514
|
// --- attributes ---------------------------------------------------------
|
|
2466
2515
|
lowerAttributes(attrs) {
|
|
2467
2516
|
const props = [];
|
|
@@ -2780,6 +2829,22 @@ var DELEGATED2 = /* @__PURE__ */ new Set([
|
|
|
2780
2829
|
"mouseup"
|
|
2781
2830
|
]);
|
|
2782
2831
|
var isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
2832
|
+
var CONTAINER2 = "container";
|
|
2833
|
+
function directive(node, name) {
|
|
2834
|
+
if (node.type !== "JSXElement") return void 0;
|
|
2835
|
+
const opening = node.openingElement;
|
|
2836
|
+
if (opening.name.type !== "JSXIdentifier" || opening.name.name[0] !== opening.name.name[0].toLowerCase()) return void 0;
|
|
2837
|
+
return opening.attributes.find((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
|
|
2838
|
+
}
|
|
2839
|
+
function directiveExpr(attr) {
|
|
2840
|
+
const v = attr.value;
|
|
2841
|
+
return v?.type === "JSXExpressionContainer" && v.expression?.type !== "JSXEmptyExpression" ? v.expression : void 0;
|
|
2842
|
+
}
|
|
2843
|
+
function emitIR(ir, ctx) {
|
|
2844
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {});
|
|
2845
|
+
for (const s of imports) ctx.used.add(s);
|
|
2846
|
+
return inlineTemplates(code, templates);
|
|
2847
|
+
}
|
|
2783
2848
|
var posOf = (node, ctx) => {
|
|
2784
2849
|
if (!ctx.sourceFile) return void 0;
|
|
2785
2850
|
const at = node.loc?.start;
|
|
@@ -2888,7 +2953,16 @@ function buildProps(attrs, ctx) {
|
|
|
2888
2953
|
}
|
|
2889
2954
|
function buildChildren(children, ctx) {
|
|
2890
2955
|
const out = [];
|
|
2891
|
-
for (
|
|
2956
|
+
for (let i = 0; i < children.length; i++) {
|
|
2957
|
+
const child = children[i];
|
|
2958
|
+
if (directive(child, "if")) {
|
|
2959
|
+
let next = i + 1;
|
|
2960
|
+
while (next < children.length && children[next].type === "JSXText" && !cleanTemplateText(children[next].value)) next++;
|
|
2961
|
+
const fallback = directive(children[next], "else") ? children[next] : null;
|
|
2962
|
+
out.push(buildIf(child, fallback, ctx));
|
|
2963
|
+
if (fallback) i = next;
|
|
2964
|
+
continue;
|
|
2965
|
+
}
|
|
2892
2966
|
if (child.type === "JSXText") {
|
|
2893
2967
|
const text = cleanTemplateText(child.value);
|
|
2894
2968
|
if (text) out.push({ kind: "text", value: text });
|
|
@@ -2925,19 +2999,68 @@ function readLoad(attrs) {
|
|
|
2925
2999
|
}
|
|
2926
3000
|
return void 0;
|
|
2927
3001
|
}
|
|
3002
|
+
function buildIf(node, fallback, ctx) {
|
|
3003
|
+
const cond = directiveExpr(directive(node, "if"));
|
|
3004
|
+
const props = [
|
|
3005
|
+
cond ? { name: "when", kind: "attr", expr: ctx.code(cond), reactive: isReactive(cond), at: posOf(cond, ctx) } : { name: "when", kind: "attr", literal: true }
|
|
3006
|
+
];
|
|
3007
|
+
if (fallback) {
|
|
3008
|
+
props.push({ name: "fallback", kind: "attr", expr: emitIR(buildElement(fallback, ctx, ["else"]), ctx), jsxElement: true });
|
|
3009
|
+
}
|
|
3010
|
+
return { kind: "component", name: "Show", props, children: [buildElement(node, ctx, ["if"])] };
|
|
3011
|
+
}
|
|
3012
|
+
function buildEach(node, ctx) {
|
|
3013
|
+
const attr = directive(node, "each");
|
|
3014
|
+
if (!attr) return null;
|
|
3015
|
+
const list = directiveExpr(attr);
|
|
3016
|
+
const props = [
|
|
3017
|
+
list ? { name: "each", kind: "attr", expr: ctx.code(list), reactive: isReactive(list), at: posOf(list, ctx) } : { name: "each", kind: "attr", expr: "[]" }
|
|
3018
|
+
];
|
|
3019
|
+
const key = directive(node, "key");
|
|
3020
|
+
if (key) {
|
|
3021
|
+
const keyExpr = directiveExpr(key);
|
|
3022
|
+
const by = isString(key.value) ? `(item) => item[${JSON.stringify(literalOf(key.value))}]` : keyExpr ? ctx.code(keyExpr) : void 0;
|
|
3023
|
+
if (by) props.push({ name: "by", kind: "attr", expr: by });
|
|
3024
|
+
}
|
|
3025
|
+
const content = node.children.filter((c) => !(c.type === "JSXText" && !cleanTemplateText(c.value)));
|
|
3026
|
+
const only = content.length === 1 && content[0].type === "JSXExpressionContainer" ? content[0].expression : null;
|
|
3027
|
+
let render;
|
|
3028
|
+
if (only && (only.type === "ArrowFunctionExpression" || only.type === "FunctionExpression")) {
|
|
3029
|
+
const fn = ctx.code(only);
|
|
3030
|
+
const live = only.type === "ArrowFunctionExpression" && only.body.type !== "BlockStatement" && isReactive(only.body);
|
|
3031
|
+
render = live ? `(...args) => () => (${fn})(...args)` : fn;
|
|
3032
|
+
} else {
|
|
3033
|
+
const built = buildChildren(node.children, ctx);
|
|
3034
|
+
const ir = built.length === 1 ? built[0] : { kind: "fragment", children: built };
|
|
3035
|
+
render = `() => ${paren(emitIR(ir, ctx), "arrowBody")}`;
|
|
3036
|
+
}
|
|
3037
|
+
return { kind: "component", name: "For", props, children: [{ kind: "expr", code: render, reactive: false }] };
|
|
3038
|
+
}
|
|
3039
|
+
function buildElement(node, ctx, handled) {
|
|
3040
|
+
const skip = new Set(handled);
|
|
3041
|
+
const directives = /* @__PURE__ */ new Set(["if", "else", "each", ...directive(node, "each") ? ["key"] : []]);
|
|
3042
|
+
const attributes = node.openingElement.attributes.filter(
|
|
3043
|
+
(a) => !(a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && (skip.has(a.name.name) || directives.has(a.name.name)))
|
|
3044
|
+
);
|
|
3045
|
+
const { tag } = tagInfo(node.openingElement.name, ctx);
|
|
3046
|
+
const each = buildEach(node, ctx);
|
|
3047
|
+
const children = each ? [each] : buildChildren(node.children, ctx);
|
|
3048
|
+
if (tag === CONTAINER2) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
3049
|
+
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
3050
|
+
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props: buildProps(attributes, ctx), children, static: false, ...at ? { at } : {} };
|
|
3051
|
+
}
|
|
2928
3052
|
function buildNode(node, ctx) {
|
|
2929
3053
|
if (node.type === "JSXFragment") {
|
|
2930
3054
|
return { kind: "fragment", children: buildChildren(node.children, ctx) };
|
|
2931
3055
|
}
|
|
3056
|
+
if (directive(node, "if")) return buildIf(node, null, ctx);
|
|
2932
3057
|
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
3058
|
+
if (!component) return buildElement(node, ctx, []);
|
|
2933
3059
|
const props = buildProps(node.openingElement.attributes, ctx);
|
|
2934
3060
|
const children = buildChildren(node.children, ctx);
|
|
2935
3061
|
const at = ctx.sourceFile && node.loc?.start ? { file: ctx.sourceFile, line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
2939
|
-
}
|
|
2940
|
-
return { kind: "element", tag, svg: SVG_TAGS.has(tag), props, children, static: false, ...at ? { at } : {} };
|
|
3062
|
+
const load = readLoad(node.openingElement.attributes);
|
|
3063
|
+
return { kind: "component", name: tag, props, children, ...load ? { load } : {}, ...at ? { at } : {} };
|
|
2941
3064
|
}
|
|
2942
3065
|
function buildJsxIR(node, ctx) {
|
|
2943
3066
|
const ir = buildNode(node, ctx);
|
|
@@ -3605,7 +3728,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3605
3728
|
const wantsJsx = format !== "lit";
|
|
3606
3729
|
const mayHaveTemplate = wantsLit && (code.includes(`${litTag}\``) || code.includes("svg`"));
|
|
3607
3730
|
const wantsIntrinsics = options.intrinsics !== false && mayHaveIntrinsic(code);
|
|
3608
|
-
const wantsSources = options.sourceLocations === true &&
|
|
3731
|
+
const wantsSources = options.sourceLocations === true && mayHaveSourceMarks(code);
|
|
3609
3732
|
const sourceName = relativeToRoot(id, options.sourceRoot);
|
|
3610
3733
|
if (!mayHaveTemplate && !(wantsJsx && code.includes("<")) && !wantsIntrinsics && !wantsSources) return null;
|
|
3611
3734
|
const ast = parse2(code, {
|
|
@@ -34,6 +34,7 @@ var INTRINSICS = {
|
|
|
34
34
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
35
35
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
36
36
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
37
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
37
38
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
38
39
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
39
40
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -44,6 +45,19 @@ var INTRINSICS = {
|
|
|
44
45
|
// dependency analysis must not guess at.
|
|
45
46
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
46
47
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
48
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
49
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
50
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
51
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
52
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
53
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
54
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
55
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
56
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
57
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
58
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
59
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
60
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
47
61
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
48
62
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
49
63
|
};
|
|
@@ -56,8 +70,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
56
70
|
createMemo: "memo-accessor",
|
|
57
71
|
createEffect: "effect",
|
|
58
72
|
createRenderEffect: "effect",
|
|
73
|
+
renderEffect: "effect",
|
|
74
|
+
computed: "effect",
|
|
59
75
|
createStore: "reactive-object",
|
|
60
76
|
resource: "resource-handle",
|
|
77
|
+
cachedResource: "resource-handle",
|
|
61
78
|
createResource: "reactive-object",
|
|
62
79
|
createSelector: "memo-accessor",
|
|
63
80
|
createDeferred: "memo-accessor"
|
|
@@ -66,6 +83,7 @@ var PRIMITIVE_MODULES = [
|
|
|
66
83
|
"@fluixi/reactive",
|
|
67
84
|
"@fluixi/reactive/signal",
|
|
68
85
|
"@fluixi/reactive/store",
|
|
86
|
+
"@fluixi/reactive/cached-resource",
|
|
69
87
|
"@fluixi/core"
|
|
70
88
|
];
|
|
71
89
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -6,6 +6,7 @@ var INTRINSICS = {
|
|
|
6
6
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
7
7
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
8
8
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
9
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
9
10
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
10
11
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
11
12
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -16,6 +17,19 @@ var INTRINSICS = {
|
|
|
16
17
|
// dependency analysis must not guess at.
|
|
17
18
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
18
19
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
20
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
21
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
22
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
23
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
24
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
25
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
26
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
27
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
28
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
29
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
30
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
31
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
32
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
19
33
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
20
34
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
21
35
|
};
|
|
@@ -28,8 +42,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
28
42
|
createMemo: "memo-accessor",
|
|
29
43
|
createEffect: "effect",
|
|
30
44
|
createRenderEffect: "effect",
|
|
45
|
+
renderEffect: "effect",
|
|
46
|
+
computed: "effect",
|
|
31
47
|
createStore: "reactive-object",
|
|
32
48
|
resource: "resource-handle",
|
|
49
|
+
cachedResource: "resource-handle",
|
|
33
50
|
createResource: "reactive-object",
|
|
34
51
|
createSelector: "memo-accessor",
|
|
35
52
|
createDeferred: "memo-accessor"
|
|
@@ -38,6 +55,7 @@ var PRIMITIVE_MODULES = [
|
|
|
38
55
|
"@fluixi/reactive",
|
|
39
56
|
"@fluixi/reactive/signal",
|
|
40
57
|
"@fluixi/reactive/store",
|
|
58
|
+
"@fluixi/reactive/cached-resource",
|
|
41
59
|
"@fluixi/core"
|
|
42
60
|
];
|
|
43
61
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/transform/source-locations.ts
|
|
21
21
|
var source_locations_exports = {};
|
|
22
22
|
__export(source_locations_exports, {
|
|
23
|
+
CLASS_MARKER: () => CLASS_MARKER,
|
|
23
24
|
COMPONENT_MARKER: () => COMPONENT_MARKER,
|
|
24
25
|
HOLE_MARKER: () => HOLE_MARKER,
|
|
25
26
|
PROPS_MARKER: () => PROPS_MARKER,
|
|
@@ -27,7 +28,7 @@ __export(source_locations_exports, {
|
|
|
27
28
|
collectSourceEdits: () => collectSourceEdits,
|
|
28
29
|
markHole: () => markHole,
|
|
29
30
|
markProps: () => markProps,
|
|
30
|
-
|
|
31
|
+
mayHaveSourceMarks: () => mayHaveSourceMarks
|
|
31
32
|
});
|
|
32
33
|
module.exports = __toCommonJS(source_locations_exports);
|
|
33
34
|
|
|
@@ -39,6 +40,7 @@ var INTRINSICS = {
|
|
|
39
40
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
40
41
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
41
42
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
43
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
42
44
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
43
45
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
44
46
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -49,6 +51,19 @@ var INTRINSICS = {
|
|
|
49
51
|
// dependency analysis must not guess at.
|
|
50
52
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
51
53
|
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
54
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
55
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
56
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
57
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
58
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
59
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
60
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
61
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
62
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
63
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
64
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
65
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
66
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
52
67
|
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
53
68
|
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
54
69
|
};
|
|
@@ -61,8 +76,11 @@ var RUNTIME_PRIMITIVES = {
|
|
|
61
76
|
createMemo: "memo-accessor",
|
|
62
77
|
createEffect: "effect",
|
|
63
78
|
createRenderEffect: "effect",
|
|
79
|
+
renderEffect: "effect",
|
|
80
|
+
computed: "effect",
|
|
64
81
|
createStore: "reactive-object",
|
|
65
82
|
resource: "resource-handle",
|
|
83
|
+
cachedResource: "resource-handle",
|
|
66
84
|
createResource: "reactive-object",
|
|
67
85
|
createSelector: "memo-accessor",
|
|
68
86
|
createDeferred: "memo-accessor"
|
|
@@ -71,6 +89,7 @@ var PRIMITIVE_MODULES = [
|
|
|
71
89
|
"@fluixi/reactive",
|
|
72
90
|
"@fluixi/reactive/signal",
|
|
73
91
|
"@fluixi/reactive/store",
|
|
92
|
+
"@fluixi/reactive/cached-resource",
|
|
74
93
|
"@fluixi/core"
|
|
75
94
|
];
|
|
76
95
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
@@ -174,6 +193,7 @@ function resolveReactiveBindings(program) {
|
|
|
174
193
|
// src/transform/source-locations.ts
|
|
175
194
|
var SOURCE_MARKER = "__fx_source";
|
|
176
195
|
var COMPONENT_MARKER = "__fx_component";
|
|
196
|
+
var CLASS_MARKER = "__fx_class";
|
|
177
197
|
var HOLE_MARKER = "__fx_hole";
|
|
178
198
|
var markHole = (accessor, line, column, name) => `(globalThis.${HOLE_MARKER} ?? ((f) => f))(${accessor},${line},${column}${name === void 0 ? "" : `,${JSON.stringify(name)}`})`;
|
|
179
199
|
var PROPS_MARKER = "__fx_props";
|
|
@@ -191,11 +211,12 @@ var RUNTIME_PRIMITIVES2 = /* @__PURE__ */ new Set([
|
|
|
191
211
|
"createStore",
|
|
192
212
|
"createResource"
|
|
193
213
|
]);
|
|
194
|
-
function
|
|
214
|
+
function mayHaveSourceMarks(code) {
|
|
195
215
|
for (const name of RUNTIME_PRIMITIVES2) {
|
|
196
216
|
if (code.includes(name)) return true;
|
|
197
217
|
}
|
|
198
|
-
|
|
218
|
+
if (code.includes("$signal") || code.includes("$memo") || code.includes("$effect") || code.includes("$store")) return true;
|
|
219
|
+
return /\bclass\b[^{;]*\bextends\b/.test(code);
|
|
199
220
|
}
|
|
200
221
|
var SINGLE_STATEMENT_PARENTS = /* @__PURE__ */ new Set([
|
|
201
222
|
"IfStatement",
|
|
@@ -214,6 +235,7 @@ function isLoneBranch(statement, parent) {
|
|
|
214
235
|
function isExport(node) {
|
|
215
236
|
return node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration";
|
|
216
237
|
}
|
|
238
|
+
var CLASS_FIELDS = /* @__PURE__ */ new Set(["PropertyDefinition", "ClassProperty", "ClassPrivateProperty", "AccessorProperty"]);
|
|
217
239
|
function isStatement(node) {
|
|
218
240
|
return node.type.endsWith("Statement") || node.type === "VariableDeclaration";
|
|
219
241
|
}
|
|
@@ -234,6 +256,14 @@ function walk2(node, visit, stack = []) {
|
|
|
234
256
|
}
|
|
235
257
|
function nameFor(stack) {
|
|
236
258
|
const declarator = stack[stack.length - 1];
|
|
259
|
+
if (declarator && CLASS_FIELDS.has(declarator.type)) {
|
|
260
|
+
const key = declarator.key;
|
|
261
|
+
if (key?.type === "Identifier" || key?.type === "PrivateIdentifier" || key?.type === "PrivateName") {
|
|
262
|
+
const name = key.name ?? key.id?.name;
|
|
263
|
+
return name;
|
|
264
|
+
}
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
237
267
|
if (declarator?.type !== "VariableDeclarator") return void 0;
|
|
238
268
|
const id = declarator.id;
|
|
239
269
|
if (id?.type === "Identifier") return id.name;
|
|
@@ -282,6 +312,17 @@ function collectSourceEdits(program, filename) {
|
|
|
282
312
|
});
|
|
283
313
|
}
|
|
284
314
|
}
|
|
315
|
+
if ((node.type === "ClassDeclaration" || node.type === "ClassExpression") && node.superClass && !node.declare) {
|
|
316
|
+
const at = node.loc?.start;
|
|
317
|
+
const body = node.body;
|
|
318
|
+
if (at && body) {
|
|
319
|
+
edits.push({
|
|
320
|
+
start: body.start + 1,
|
|
321
|
+
end: body.start + 1,
|
|
322
|
+
code: `static{globalThis.${CLASS_MARKER}?.(this,${JSON.stringify(filename)},${at.line},${at.column});}`
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
285
326
|
if (node.type !== "CallExpression") return;
|
|
286
327
|
const callee = node.callee;
|
|
287
328
|
if (callee?.type !== "Identifier") return;
|
|
@@ -291,6 +332,26 @@ function collectSourceEdits(program, filename) {
|
|
|
291
332
|
if (!intrinsic && !imported) return;
|
|
292
333
|
const position = node.loc?.start;
|
|
293
334
|
if (!position) return;
|
|
335
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
336
|
+
const up = stack[i];
|
|
337
|
+
if (isStatement(up)) break;
|
|
338
|
+
if (CLASS_FIELDS.has(up.type)) {
|
|
339
|
+
if (claimed.has(node.start)) return;
|
|
340
|
+
claimed.add(node.start);
|
|
341
|
+
const label2 = nameFor(stack);
|
|
342
|
+
const own = !up.static;
|
|
343
|
+
const args2 = [
|
|
344
|
+
JSON.stringify(filename),
|
|
345
|
+
String(position.line),
|
|
346
|
+
String(position.column),
|
|
347
|
+
label2 ? JSON.stringify(label2) : own ? "undefined" : void 0,
|
|
348
|
+
own ? "this" : void 0
|
|
349
|
+
].filter((a) => a !== void 0).join(",");
|
|
350
|
+
edits.push({ start: node.start, end: node.start, code: `(globalThis.${SOURCE_MARKER}?.(${args2}),` });
|
|
351
|
+
edits.push({ start: node.end, end: node.end, code: ")" });
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
294
355
|
let statement;
|
|
295
356
|
let parent;
|
|
296
357
|
let index = -1;
|
|
@@ -12,6 +12,11 @@ export interface SourceLocationsResult {
|
|
|
12
12
|
export declare const SOURCE_MARKER = "__fx_source";
|
|
13
13
|
/** Where a component was declared. Keyed by name, since that is all the runtime carries. */
|
|
14
14
|
export declare const COMPONENT_MARKER = "__fx_component";
|
|
15
|
+
/**
|
|
16
|
+
* Where a class that extends another was declared, keyed by the class itself: a custom
|
|
17
|
+
* element's definition, which the runtime can only reach through `element.constructor`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CLASS_MARKER = "__fx_class";
|
|
15
20
|
/**
|
|
16
21
|
* Where one reactive hole was written. This one wraps: the position has to travel with the
|
|
17
22
|
* accessor to wherever the dom wires it up. A template is emitted as one overwrite, so the
|
|
@@ -38,6 +43,6 @@ export declare const markHole: (accessor: string, line: number, column: number,
|
|
|
38
43
|
export declare const PROPS_MARKER = "__fx_props";
|
|
39
44
|
/** `_({ get a() {…} }, {"a":[9,25]})`, or the object untouched when nothing is watching. */
|
|
40
45
|
export declare const markProps: (object: string, at: Record<string, [number, number]>) => string;
|
|
41
|
-
/** Cheap enough to run before parsing. */
|
|
42
|
-
export declare function
|
|
46
|
+
/** Whether a module has anything to mark: a primitive call or a subclass. Cheap enough to run before parsing. */
|
|
47
|
+
export declare function mayHaveSourceMarks(code: string): boolean;
|
|
43
48
|
export declare function collectSourceEdits(program: unknown, filename: string): SourceLocationsResult;
|