@fluixi/compiler 1.0.0-alpha.91 → 1.0.0-alpha.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyze/intrinsics.cjs +21 -1
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +20 -0
- package/dist/analyze/intrinsics.mjs +21 -1
- package/dist/analyze/reactive-bindings.cjs +21 -1
- package/dist/analyze/reactive-bindings.mjs +21 -1
- package/dist/analyze/static-graph.cjs +25 -5
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +6 -4
- package/dist/analyze/static-graph.mjs +25 -5
- package/dist/{babel-VBLQRHQ2.mjs → babel-RJHJQVEM.mjs} +4 -4
- package/dist/{chunk-D53J7ICY.mjs → chunk-56QSOVVL.mjs} +1 -1
- package/dist/{chunk-S4J4OCWK.mjs → chunk-OD53TMER.mjs} +22 -2
- package/dist/{chunk-TWDJUXWZ.mjs → chunk-R7PPFBCL.mjs} +1 -1
- package/dist/{chunk-QX6Y3OAR.mjs → chunk-TJIH7TLX.mjs} +1 -1
- package/dist/{chunk-3JWMCK4A.mjs → chunk-U7HCFLZ2.mjs} +153 -48
- package/dist/codegen/backends/imperative.cjs +27 -7
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +19 -4
- package/dist/codegen/backends/imperative.mjs +27 -7
- package/dist/frontend/babel/build-ir-lit.cjs +123 -44
- package/dist/frontend/babel/build-ir-lit.mjs +123 -44
- package/dist/frontend/babel/build-ir.cjs +123 -44
- package/dist/frontend/babel/build-ir.mjs +123 -44
- package/dist/frontend/babel/index.cjs +124 -45
- package/dist/frontend/babel/index.mjs +124 -45
- package/dist/frontend/babel/lower-template.cjs +123 -44
- package/dist/frontend/babel/lower-template.mjs +123 -44
- package/dist/frontend/babel/plugin.cjs +123 -44
- package/dist/frontend/babel/plugin.mjs +123 -44
- package/dist/index.cjs +86 -46
- package/dist/index.mjs +88 -48
- package/dist/integrations.cjs +246 -61
- package/dist/integrations.mjs +53 -19
- package/dist/lower/compile-template.cjs +44 -39
- package/dist/lower/compile-template.mjs +44 -39
- package/dist/lower/jsx.cjs +509 -6
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +114 -6
- package/dist/lower/jsx.mjs +509 -6
- package/dist/lower/template.cjs +43 -38
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +22 -30
- package/dist/lower/template.mjs +43 -38
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +33 -8
- package/dist/resolve/component-globals.d.cts +8 -0
- package/dist/resolve/component-globals.d.ts +8 -0
- package/dist/resolve/component-globals.d.ts.map +1 -1
- package/dist/resolve/component-globals.js +21 -12
- package/dist/resolve/component-globals.mjs +33 -8
- package/dist/resolve/write-globals.cjs +59 -8
- package/dist/resolve/write-globals.d.cts +6 -0
- package/dist/resolve/write-globals.d.ts +6 -0
- package/dist/resolve/write-globals.d.ts.map +1 -1
- package/dist/resolve/write-globals.js +35 -2
- package/dist/resolve/write-globals.mjs +61 -10
- package/dist/{server-fns-J56G3PFP.mjs → server-fns-ZFRDIQ2X.mjs} +4 -4
- package/dist/{server-functions-7PUFLRGF.mjs → server-functions-CTDXX67X.mjs} +3 -3
- package/dist/transform/index.cjs +199 -49
- package/dist/transform/index.mjs +199 -49
- package/dist/transform/intrinsics.cjs +47 -2
- package/dist/transform/intrinsics.d.cts +12 -0
- package/dist/transform/intrinsics.d.ts +12 -0
- package/dist/transform/intrinsics.d.ts.map +1 -1
- package/dist/transform/intrinsics.js +43 -1
- package/dist/transform/intrinsics.mjs +47 -2
- package/dist/transform/source-locations.cjs +67 -4
- package/dist/transform/source-locations.d.cts +7 -2
- package/dist/transform/source-locations.d.ts +7 -2
- package/dist/transform/source-locations.d.ts.map +1 -1
- package/dist/transform/source-locations.js +68 -3
- package/dist/transform/source-locations.mjs +67 -4
- package/dist/transform/templates.cjs +198 -48
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +5 -3
- package/dist/transform/templates.mjs +198 -48
- package/dist/{transform-D536WXGM.mjs → transform-QWWQDCXE.mjs} +33 -8
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -3
package/dist/lower/template.cjs
CHANGED
|
@@ -283,6 +283,7 @@ var INTRINSICS = {
|
|
|
283
283
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
284
284
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
285
285
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
286
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
286
287
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
287
288
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
288
289
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -292,7 +293,22 @@ var INTRINSICS = {
|
|
|
292
293
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
293
294
|
// dependency analysis must not guess at.
|
|
294
295
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
295
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
296
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
297
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
298
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
299
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
300
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
301
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
302
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
303
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
304
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
305
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
306
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
307
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
308
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
309
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
310
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
311
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
296
312
|
};
|
|
297
313
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
298
314
|
|
|
@@ -468,13 +484,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
468
484
|
used.add("createComponent");
|
|
469
485
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
470
486
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
471
|
-
const
|
|
472
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
473
|
-
);
|
|
487
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
474
488
|
if (children.length > 0) {
|
|
475
|
-
|
|
489
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
490
|
+
}
|
|
491
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
492
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
493
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
494
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
495
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
476
496
|
}
|
|
477
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
478
497
|
if (spreads.length > 0) {
|
|
479
498
|
used.add("mergeProps");
|
|
480
499
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -556,7 +575,8 @@ function emitNode(node, used, templates) {
|
|
|
556
575
|
} else {
|
|
557
576
|
used.add("spread");
|
|
558
577
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
559
|
-
const
|
|
578
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
579
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
560
580
|
parts.push(
|
|
561
581
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
562
582
|
);
|
|
@@ -627,6 +647,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
627
647
|
function escapeTemplate(s) {
|
|
628
648
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
629
649
|
}
|
|
650
|
+
var CONTAINER = "container";
|
|
630
651
|
function capitalize(s) {
|
|
631
652
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
632
653
|
}
|
|
@@ -681,10 +702,6 @@ var Lowerer = class {
|
|
|
681
702
|
if (hasElse) i = elseIdx;
|
|
682
703
|
continue;
|
|
683
704
|
}
|
|
684
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
685
|
-
out.push(this.lowerEach(child));
|
|
686
|
-
continue;
|
|
687
|
-
}
|
|
688
705
|
}
|
|
689
706
|
const node = this.lowerNode(child);
|
|
690
707
|
if (node) out.push(node);
|
|
@@ -726,13 +743,16 @@ var Lowerer = class {
|
|
|
726
743
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
727
744
|
return node;
|
|
728
745
|
}
|
|
746
|
+
const each = this.lowerEach(el);
|
|
747
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
748
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
729
749
|
const at = this.tagAt(el);
|
|
730
750
|
return {
|
|
731
751
|
kind: "element",
|
|
732
752
|
tag: el.tag,
|
|
733
753
|
svg: el.namespace === "svg",
|
|
734
754
|
props: this.lowerAttributes(el.attributes),
|
|
735
|
-
children
|
|
755
|
+
children,
|
|
736
756
|
static: false,
|
|
737
757
|
...at ? { at } : {}
|
|
738
758
|
};
|
|
@@ -804,10 +824,14 @@ var Lowerer = class {
|
|
|
804
824
|
const at = this.tagAt(el);
|
|
805
825
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
806
826
|
}
|
|
807
|
-
/**
|
|
827
|
+
/**
|
|
828
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
829
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
830
|
+
* it is. Null when the element has no `each`.
|
|
831
|
+
*/
|
|
808
832
|
lowerEach(el) {
|
|
809
833
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
810
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
834
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
811
835
|
const each = this.hole(eachDir.hole);
|
|
812
836
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
813
837
|
if (eachDir.key) {
|
|
@@ -817,12 +841,12 @@ var Lowerer = class {
|
|
|
817
841
|
const arrow = this.itemArrow(el);
|
|
818
842
|
let childrenCode;
|
|
819
843
|
if (arrow) {
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
844
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
845
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
823
846
|
} else {
|
|
824
|
-
const
|
|
825
|
-
|
|
847
|
+
const content = this.lowerChildren(el.children);
|
|
848
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
849
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
826
850
|
}
|
|
827
851
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
828
852
|
const at = this.tagAt(el);
|
|
@@ -839,25 +863,6 @@ var Lowerer = class {
|
|
|
839
863
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
840
864
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
841
865
|
}
|
|
842
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
843
|
-
rebuildWithChildren(el, children) {
|
|
844
|
-
const props = this.lowerAttributes(
|
|
845
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
846
|
-
);
|
|
847
|
-
if (el.kind === "Element") {
|
|
848
|
-
const at = this.tagAt(el);
|
|
849
|
-
return {
|
|
850
|
-
kind: "element",
|
|
851
|
-
tag: el.tag,
|
|
852
|
-
svg: el.namespace === "svg",
|
|
853
|
-
props,
|
|
854
|
-
children,
|
|
855
|
-
static: false,
|
|
856
|
-
...at ? { at } : {}
|
|
857
|
-
};
|
|
858
|
-
}
|
|
859
|
-
return { kind: "component", name: el.tag, props, children };
|
|
860
|
-
}
|
|
861
866
|
// --- attributes ---------------------------------------------------------
|
|
862
867
|
lowerAttributes(attrs) {
|
|
863
868
|
const props = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/lower/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAML,KAAK,KAAK,EAGX,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAsB,MAAM,gBAAgB,CAAC;AAM/E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAClE,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,YAAY,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/lower/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAML,KAAK,KAAK,EAGX,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAsB,MAAM,gBAAgB,CAAC;AAM/E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,CAAC;IAClE,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,YAAY,CAAC;CACnB;AAwgBD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,EAAE,YAAY,EAAE,EACrB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EACjB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAO,GACnH,MAAM,CAGR"}
|
package/dist/lower/template.js
CHANGED
|
@@ -19,6 +19,8 @@ const DELEGATED = new Set([
|
|
|
19
19
|
function escapeTemplate(s) {
|
|
20
20
|
return s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
21
21
|
}
|
|
22
|
+
/** The tag that carries directives and renders only its content. Never a custom element: no dash. */
|
|
23
|
+
const CONTAINER = 'container';
|
|
22
24
|
function capitalize(s) {
|
|
23
25
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
24
26
|
}
|
|
@@ -88,10 +90,6 @@ class Lowerer {
|
|
|
88
90
|
i = elseIdx;
|
|
89
91
|
continue;
|
|
90
92
|
}
|
|
91
|
-
if (child.attributes.some((a) => a.kind === 'EachDirective')) {
|
|
92
|
-
out.push(this.lowerEach(child));
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
93
|
}
|
|
96
94
|
const node = this.lowerNode(child);
|
|
97
95
|
if (node)
|
|
@@ -137,13 +135,19 @@ class Lowerer {
|
|
|
137
135
|
node.props.unshift({ name: 'component', kind: 'attr', expr: `() => ${paren(this.hole(isAttr.value.hole).code, 'arrowBody')}` });
|
|
138
136
|
return node;
|
|
139
137
|
}
|
|
138
|
+
// `each` repeats the element's content, never the element: `<ul each>` is one list.
|
|
139
|
+
const each = this.lowerEach(el);
|
|
140
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
141
|
+
// A `<container>` is only what it holds. It carries the directives and is never rendered.
|
|
142
|
+
if (el.tag === CONTAINER)
|
|
143
|
+
return children.length === 1 ? children[0] : { kind: 'fragment', children };
|
|
140
144
|
const at = this.tagAt(el);
|
|
141
145
|
return {
|
|
142
146
|
kind: 'element',
|
|
143
147
|
tag: el.tag,
|
|
144
148
|
svg: el.namespace === 'svg',
|
|
145
149
|
props: this.lowerAttributes(el.attributes),
|
|
146
|
-
children
|
|
150
|
+
children,
|
|
147
151
|
static: false,
|
|
148
152
|
...(at ? { at } : {}),
|
|
149
153
|
};
|
|
@@ -233,11 +237,15 @@ class Lowerer {
|
|
|
233
237
|
const at = this.tagAt(el);
|
|
234
238
|
return { kind: 'component', name: 'Show', props, children: [child], ...(at ? { at } : {}), ...(cond.at ? { bindAt: cond.at } : {}) };
|
|
235
239
|
}
|
|
236
|
-
/**
|
|
240
|
+
/**
|
|
241
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
242
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
243
|
+
* it is. Null when the element has no `each`.
|
|
244
|
+
*/
|
|
237
245
|
lowerEach(el) {
|
|
238
246
|
const eachDir = el.attributes.find((a) => a.kind === 'EachDirective');
|
|
239
247
|
if (!eachDir || eachDir.kind !== 'EachDirective')
|
|
240
|
-
return
|
|
248
|
+
return null;
|
|
241
249
|
const each = this.hole(eachDir.hole);
|
|
242
250
|
const props = [{ name: 'each', kind: 'attr', expr: each.code, reactive: each.reactive, ...(each.at ? { at: each.at } : {}) }];
|
|
243
251
|
if (eachDir.key) {
|
|
@@ -248,17 +256,18 @@ class Lowerer {
|
|
|
248
256
|
: this.hole(eachDir.key.hole).code;
|
|
249
257
|
props.push({ name: 'by', kind: 'attr', expr: by });
|
|
250
258
|
}
|
|
251
|
-
// The element minus its each/key, repeated per item.
|
|
252
259
|
const arrow = this.itemArrow(el);
|
|
253
260
|
let childrenCode;
|
|
254
261
|
if (arrow) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
262
|
+
// A body that reads signals, `${(it) => it.label + count()}`, stays live: it is handed
|
|
263
|
+
// back as an accessor for the runtime to bind, as it was inside the repeated element.
|
|
264
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, 'arrowBody')}` : paren(arrow.body, 'arrowBody');
|
|
265
|
+
childrenCode = `(${arrow.params.join(', ')}) => ${body}`;
|
|
258
266
|
}
|
|
259
267
|
else {
|
|
260
|
-
const
|
|
261
|
-
|
|
268
|
+
const content = this.lowerChildren(el.children);
|
|
269
|
+
const ir = content.length === 1 ? content[0] : { kind: 'fragment', children: content };
|
|
270
|
+
childrenCode = `() => ${paren(this.emit(ir), 'arrowBody')}`;
|
|
262
271
|
}
|
|
263
272
|
const children = [{ kind: 'expr', code: childrenCode, reactive: false }];
|
|
264
273
|
const at = this.tagAt(el);
|
|
@@ -276,23 +285,6 @@ class Lowerer {
|
|
|
276
285
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
277
286
|
return clone.kind === 'Element' ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
278
287
|
}
|
|
279
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
280
|
-
rebuildWithChildren(el, children) {
|
|
281
|
-
const props = this.lowerAttributes(el.attributes.filter((a) => a.kind !== 'EachDirective'));
|
|
282
|
-
if (el.kind === 'Element') {
|
|
283
|
-
const at = this.tagAt(el);
|
|
284
|
-
return {
|
|
285
|
-
kind: 'element',
|
|
286
|
-
tag: el.tag,
|
|
287
|
-
svg: el.namespace === 'svg',
|
|
288
|
-
props,
|
|
289
|
-
children,
|
|
290
|
-
static: false,
|
|
291
|
-
...(at ? { at } : {}),
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
return { kind: 'component', name: el.tag, props, children };
|
|
295
|
-
}
|
|
296
288
|
// --- attributes ---------------------------------------------------------
|
|
297
289
|
lowerAttributes(attrs) {
|
|
298
290
|
const props = [];
|
package/dist/lower/template.mjs
CHANGED
|
@@ -261,6 +261,7 @@ var INTRINSICS = {
|
|
|
261
261
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
262
262
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
263
263
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
264
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
264
265
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
265
266
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
266
267
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -270,7 +271,22 @@ var INTRINSICS = {
|
|
|
270
271
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
271
272
|
// dependency analysis must not guess at.
|
|
272
273
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
273
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
274
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
275
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
276
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
277
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
278
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
279
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
280
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
281
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
282
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
283
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
284
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
285
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
286
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
287
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
288
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
289
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
274
290
|
};
|
|
275
291
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
276
292
|
|
|
@@ -446,13 +462,16 @@ function emitComponent(name, props, children, used, templates, at) {
|
|
|
446
462
|
used.add("createComponent");
|
|
447
463
|
const spreads = props.filter((p) => p.kind === "spread");
|
|
448
464
|
const normal = props.filter((p) => p.kind !== "spread");
|
|
449
|
-
const
|
|
450
|
-
(p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
|
|
451
|
-
);
|
|
465
|
+
const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
|
|
452
466
|
if (children.length > 0) {
|
|
453
|
-
|
|
467
|
+
bodies.push(["children", emitChildren(children, used, templates)]);
|
|
468
|
+
}
|
|
469
|
+
let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
|
|
470
|
+
if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
|
|
471
|
+
const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => ${body}`);
|
|
472
|
+
const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
|
|
473
|
+
obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
|
|
454
474
|
}
|
|
455
|
-
let obj = `{ ${entries.join(", ")} }`;
|
|
456
475
|
if (spreads.length > 0) {
|
|
457
476
|
used.add("mergeProps");
|
|
458
477
|
obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
|
|
@@ -534,7 +553,8 @@ function emitNode(node, used, templates) {
|
|
|
534
553
|
} else {
|
|
535
554
|
used.add("spread");
|
|
536
555
|
const svgFlag = node.svg ? ", isSVG: true" : "";
|
|
537
|
-
const
|
|
556
|
+
const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
|
|
557
|
+
const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
|
|
538
558
|
parts.push(
|
|
539
559
|
`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
|
|
540
560
|
);
|
|
@@ -605,6 +625,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
|
|
|
605
625
|
function escapeTemplate(s) {
|
|
606
626
|
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
607
627
|
}
|
|
628
|
+
var CONTAINER = "container";
|
|
608
629
|
function capitalize(s) {
|
|
609
630
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
610
631
|
}
|
|
@@ -659,10 +680,6 @@ var Lowerer = class {
|
|
|
659
680
|
if (hasElse) i = elseIdx;
|
|
660
681
|
continue;
|
|
661
682
|
}
|
|
662
|
-
if (child.attributes.some((a) => a.kind === "EachDirective")) {
|
|
663
|
-
out.push(this.lowerEach(child));
|
|
664
|
-
continue;
|
|
665
|
-
}
|
|
666
683
|
}
|
|
667
684
|
const node = this.lowerNode(child);
|
|
668
685
|
if (node) out.push(node);
|
|
@@ -704,13 +721,16 @@ var Lowerer = class {
|
|
|
704
721
|
node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
|
|
705
722
|
return node;
|
|
706
723
|
}
|
|
724
|
+
const each = this.lowerEach(el);
|
|
725
|
+
const children = each ? [each] : this.lowerChildren(el.children);
|
|
726
|
+
if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
|
|
707
727
|
const at = this.tagAt(el);
|
|
708
728
|
return {
|
|
709
729
|
kind: "element",
|
|
710
730
|
tag: el.tag,
|
|
711
731
|
svg: el.namespace === "svg",
|
|
712
732
|
props: this.lowerAttributes(el.attributes),
|
|
713
|
-
children
|
|
733
|
+
children,
|
|
714
734
|
static: false,
|
|
715
735
|
...at ? { at } : {}
|
|
716
736
|
};
|
|
@@ -782,10 +802,14 @@ var Lowerer = class {
|
|
|
782
802
|
const at = this.tagAt(el);
|
|
783
803
|
return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
|
|
784
804
|
}
|
|
785
|
-
/**
|
|
805
|
+
/**
|
|
806
|
+
* `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
|
|
807
|
+
* content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
|
|
808
|
+
* it is. Null when the element has no `each`.
|
|
809
|
+
*/
|
|
786
810
|
lowerEach(el) {
|
|
787
811
|
const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
|
|
788
|
-
if (!eachDir || eachDir.kind !== "EachDirective") return
|
|
812
|
+
if (!eachDir || eachDir.kind !== "EachDirective") return null;
|
|
789
813
|
const each = this.hole(eachDir.hole);
|
|
790
814
|
const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
|
|
791
815
|
if (eachDir.key) {
|
|
@@ -795,12 +819,12 @@ var Lowerer = class {
|
|
|
795
819
|
const arrow = this.itemArrow(el);
|
|
796
820
|
let childrenCode;
|
|
797
821
|
if (arrow) {
|
|
798
|
-
const
|
|
799
|
-
|
|
800
|
-
childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
|
|
822
|
+
const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
|
|
823
|
+
childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
|
|
801
824
|
} else {
|
|
802
|
-
const
|
|
803
|
-
|
|
825
|
+
const content = this.lowerChildren(el.children);
|
|
826
|
+
const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
|
|
827
|
+
childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
|
|
804
828
|
}
|
|
805
829
|
const children = [{ kind: "expr", code: childrenCode, reactive: false }];
|
|
806
830
|
const at = this.tagAt(el);
|
|
@@ -817,25 +841,6 @@ var Lowerer = class {
|
|
|
817
841
|
const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
|
|
818
842
|
return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
|
|
819
843
|
}
|
|
820
|
-
/** Same element (minus each/key) but with explicit IR children. */
|
|
821
|
-
rebuildWithChildren(el, children) {
|
|
822
|
-
const props = this.lowerAttributes(
|
|
823
|
-
el.attributes.filter((a) => a.kind !== "EachDirective")
|
|
824
|
-
);
|
|
825
|
-
if (el.kind === "Element") {
|
|
826
|
-
const at = this.tagAt(el);
|
|
827
|
-
return {
|
|
828
|
-
kind: "element",
|
|
829
|
-
tag: el.tag,
|
|
830
|
-
svg: el.namespace === "svg",
|
|
831
|
-
props,
|
|
832
|
-
children,
|
|
833
|
-
static: false,
|
|
834
|
-
...at ? { at } : {}
|
|
835
|
-
};
|
|
836
|
-
}
|
|
837
|
-
return { kind: "component", name: el.tag, props, children };
|
|
838
|
-
}
|
|
839
844
|
// --- attributes ---------------------------------------------------------
|
|
840
845
|
lowerAttributes(attrs) {
|
|
841
846
|
const props = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -124,6 +124,7 @@ var INTRINSICS = {
|
|
|
124
124
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
125
125
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
126
126
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
127
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
127
128
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
128
129
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
129
130
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -133,7 +134,22 @@ var INTRINSICS = {
|
|
|
133
134
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
134
135
|
// dependency analysis must not guess at.
|
|
135
136
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
136
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
137
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
138
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
139
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
140
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
141
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
142
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
143
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
144
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
145
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
146
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
147
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
148
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
149
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
150
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
151
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
152
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
137
153
|
};
|
|
138
154
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
139
155
|
|
|
@@ -175,7 +191,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
175
191
|
builtins = true,
|
|
176
192
|
intrinsics = true,
|
|
177
193
|
generator = "@fluixi/compiler",
|
|
178
|
-
specifier = (module2) => module2
|
|
194
|
+
specifier = (module2) => module2,
|
|
195
|
+
candidates = []
|
|
179
196
|
} = options;
|
|
180
197
|
const all = [...rules];
|
|
181
198
|
if (builtins) {
|
|
@@ -187,7 +204,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
187
204
|
const shadowedByDom = [];
|
|
188
205
|
const unavailable = [];
|
|
189
206
|
const resolved = /* @__PURE__ */ new Map();
|
|
190
|
-
|
|
207
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
208
|
+
for (const name of [...names].sort()) {
|
|
191
209
|
const target = resolver.resolve(name);
|
|
192
210
|
if (!target) continue;
|
|
193
211
|
const pkg = packageOf(target.module);
|
|
@@ -198,7 +216,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
198
216
|
resolved.set(name, target);
|
|
199
217
|
}
|
|
200
218
|
}
|
|
201
|
-
const
|
|
219
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
220
|
+
const pkg = packageOf(i.module);
|
|
221
|
+
return !available || !pkg || available.has(pkg);
|
|
222
|
+
}) : [];
|
|
223
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
202
224
|
const modules = [
|
|
203
225
|
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
204
226
|
].sort();
|
|
@@ -218,15 +240,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
218
240
|
return `// import { ${n} } from '${module2 ? specifier(module2) : ""}';
|
|
219
241
|
`;
|
|
220
242
|
}).join("") : "";
|
|
221
|
-
const intrinsicLines =
|
|
243
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
222
244
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
223
|
-
)
|
|
245
|
+
);
|
|
224
246
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
225
|
-
const patternNote = patternRules
|
|
247
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
248
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
249
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
250
|
+
` : `//
|
|
226
251
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
227
252
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
228
253
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
229
|
-
|
|
254
|
+
`;
|
|
230
255
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
231
256
|
//
|
|
232
257
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -46,6 +46,14 @@ export interface ComponentGlobalsOptions {
|
|
|
46
46
|
* "Cannot find name '$signal'" for code that builds correctly.
|
|
47
47
|
*/
|
|
48
48
|
intrinsics?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Names to try against the pattern rules.
|
|
51
|
+
*
|
|
52
|
+
* A pattern has no name list of its own, but the files it points at do: the caller lists
|
|
53
|
+
* them (the generator stays off the filesystem) and each name the resolver answers is
|
|
54
|
+
* declared like any other.
|
|
55
|
+
*/
|
|
56
|
+
candidates?: Iterable<string>;
|
|
49
57
|
/** Attribution written into the header. */
|
|
50
58
|
generator?: string;
|
|
51
59
|
/**
|
|
@@ -46,6 +46,14 @@ export interface ComponentGlobalsOptions {
|
|
|
46
46
|
* "Cannot find name '$signal'" for code that builds correctly.
|
|
47
47
|
*/
|
|
48
48
|
intrinsics?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Names to try against the pattern rules.
|
|
51
|
+
*
|
|
52
|
+
* A pattern has no name list of its own, but the files it points at do: the caller lists
|
|
53
|
+
* them (the generator stays off the filesystem) and each name the resolver answers is
|
|
54
|
+
* declared like any other.
|
|
55
|
+
*/
|
|
56
|
+
candidates?: Iterable<string>;
|
|
49
57
|
/** Attribution written into the header. */
|
|
50
58
|
generator?: string;
|
|
51
59
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/component-globals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAC;AAmCjC,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACrC,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,qEAAqE;IACrE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAgBD,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,qBAAqB,EAAE,EACvC,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"component-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/component-globals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAC;AAmCjC,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACrC,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,qEAAqE;IACrE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAgBD,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,qBAAqB,EAAE,EACvC,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAoHxB"}
|
|
@@ -65,7 +65,7 @@ function namespaceAlias(module) {
|
|
|
65
65
|
}
|
|
66
66
|
/** Build the ambient `.d.ts` for the components a project's `resolve` config supplies. */
|
|
67
67
|
export function componentGlobals(rules, options = {}) {
|
|
68
|
-
const { available: availableList, builtins = true, intrinsics = true, generator = '@fluixi/compiler', specifier = (module) => module, } = options;
|
|
68
|
+
const { available: availableList, builtins = true, intrinsics = true, generator = '@fluixi/compiler', specifier = (module) => module, candidates = [], } = options;
|
|
69
69
|
const all = [...rules];
|
|
70
70
|
if (builtins) {
|
|
71
71
|
// Appended, so an explicit rule for the same name still wins, the resolver is
|
|
@@ -78,9 +78,9 @@ export function componentGlobals(rules, options = {}) {
|
|
|
78
78
|
const shadowedByDom = [];
|
|
79
79
|
const unavailable = [];
|
|
80
80
|
const resolved = new Map();
|
|
81
|
-
|
|
81
|
+
const names = new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
82
|
+
for (const name of [...names].sort()) {
|
|
82
83
|
const target = resolver.resolve(name);
|
|
83
|
-
/* c8 ignore next */
|
|
84
84
|
if (!target)
|
|
85
85
|
continue;
|
|
86
86
|
const pkg = packageOf(target.module);
|
|
@@ -97,7 +97,15 @@ export function componentGlobals(rules, options = {}) {
|
|
|
97
97
|
// '$signal'" for code that compiles. tsc doesn't load language-service plugins, so an
|
|
98
98
|
// ambient declaration is the only thing that answers for both the editor and the
|
|
99
99
|
// command line.
|
|
100
|
-
|
|
100
|
+
// Only the intrinsics whose package the project has: `$env` comes from `@fluixi/start`, and
|
|
101
|
+
// an app without it would otherwise get a declaration that fails to resolve.
|
|
102
|
+
const usableIntrinsics = intrinsics
|
|
103
|
+
? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
104
|
+
const pkg = packageOf(i.module);
|
|
105
|
+
return !available || !pkg || available.has(pkg);
|
|
106
|
+
})
|
|
107
|
+
: [];
|
|
108
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
101
109
|
const modules = [
|
|
102
110
|
...new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules]),
|
|
103
111
|
].sort();
|
|
@@ -130,15 +138,16 @@ export function componentGlobals(rules, options = {}) {
|
|
|
130
138
|
// `typeof ns.signal` rather than an alias: the intrinsic is a global that stands for
|
|
131
139
|
// the runtime call, so it takes the runtime's signature without claiming to be that
|
|
132
140
|
// symbol: go-to-definition on `$signal` should land on what it compiles to.
|
|
133
|
-
const intrinsicLines =
|
|
134
|
-
? Object.entries(INTRINSICS).map(([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`)
|
|
135
|
-
: [];
|
|
141
|
+
const intrinsicLines = usableIntrinsics.map(([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`);
|
|
136
142
|
const patternRules = rules.filter((rule) => 'match' in rule).length;
|
|
137
|
-
const patternNote = patternRules
|
|
138
|
-
?
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
const patternNote = patternRules === 0
|
|
144
|
+
? ''
|
|
145
|
+
: options.candidates
|
|
146
|
+
? `//\n// ${patternRules} pattern rule${patternRules === 1 ? '' : 's'}: declared for the files the module path\n` +
|
|
147
|
+
`// points at. A name with no such file still resolves at build time; declare it by hand.\n`
|
|
148
|
+
: `//\n// ${patternRules} pattern rule${patternRules === 1 ? '' : 's'} cannot be declared:\n` +
|
|
149
|
+
`// a pattern matches unboundedly many names, so there is no list to emit. Those\n` +
|
|
150
|
+
`// tags still resolve at build time; declare them by hand if the editor needs them.\n`;
|
|
142
151
|
const source = `// GENERATED by ${generator}, do not edit.\n` +
|
|
143
152
|
`//\n` +
|
|
144
153
|
`// The components \`resolve\` supplies without an import. This describes what the\n` +
|