@fluixi/compiler 1.0.0-alpha.91 → 1.0.0-alpha.92
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 +3 -1
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +2 -0
- package/dist/analyze/intrinsics.mjs +3 -1
- package/dist/analyze/reactive-bindings.cjs +3 -1
- package/dist/analyze/reactive-bindings.mjs +3 -1
- package/dist/analyze/static-graph.cjs +4 -2
- package/dist/analyze/static-graph.mjs +4 -2
- package/dist/{babel-VBLQRHQ2.mjs → babel-GI375YZ2.mjs} +4 -4
- package/dist/{chunk-TWDJUXWZ.mjs → chunk-DWNWN5RH.mjs} +1 -1
- package/dist/{chunk-D53J7ICY.mjs → chunk-QZ4CJPYP.mjs} +1 -1
- package/dist/{chunk-3JWMCK4A.mjs → chunk-VC6X44FS.mjs} +2 -2
- package/dist/{chunk-QX6Y3OAR.mjs → chunk-VOUI6XPV.mjs} +1 -1
- package/dist/{chunk-S4J4OCWK.mjs → chunk-XJ5H2MXY.mjs} +4 -2
- package/dist/codegen/backends/imperative.cjs +3 -1
- package/dist/codegen/backends/imperative.mjs +3 -1
- package/dist/frontend/babel/build-ir-lit.cjs +3 -1
- package/dist/frontend/babel/build-ir-lit.mjs +3 -1
- package/dist/frontend/babel/build-ir.cjs +3 -1
- package/dist/frontend/babel/build-ir.mjs +3 -1
- package/dist/frontend/babel/index.cjs +4 -2
- package/dist/frontend/babel/index.mjs +4 -2
- package/dist/frontend/babel/lower-template.cjs +3 -1
- package/dist/frontend/babel/lower-template.mjs +3 -1
- package/dist/frontend/babel/plugin.cjs +3 -1
- package/dist/frontend/babel/plugin.mjs +3 -1
- package/dist/index.cjs +46 -9
- package/dist/index.mjs +48 -11
- package/dist/integrations.cjs +71 -10
- package/dist/integrations.mjs +53 -19
- package/dist/lower/compile-template.cjs +4 -2
- package/dist/lower/compile-template.mjs +4 -2
- package/dist/lower/template.cjs +3 -1
- package/dist/lower/template.mjs +3 -1
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +19 -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 +19 -8
- package/dist/resolve/write-globals.cjs +45 -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 +47 -10
- package/dist/{server-fns-J56G3PFP.mjs → server-fns-BBZRZUPP.mjs} +4 -4
- package/dist/{server-functions-7PUFLRGF.mjs → server-functions-VEGLIFCE.mjs} +3 -3
- package/dist/transform/index.cjs +30 -3
- package/dist/transform/index.mjs +30 -3
- package/dist/transform/intrinsics.cjs +29 -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 +29 -2
- package/dist/transform/source-locations.cjs +3 -1
- package/dist/transform/source-locations.mjs +3 -1
- package/dist/transform/templates.cjs +29 -2
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +3 -1
- package/dist/transform/templates.mjs +29 -2
- package/dist/{transform-D536WXGM.mjs → transform-UWZ7ZGJ2.mjs} +31 -6
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var write_globals_exports = {};
|
|
22
22
|
__export(write_globals_exports, {
|
|
23
23
|
DEFAULT_GLOBALS_PATH: () => DEFAULT_GLOBALS_PATH,
|
|
24
|
+
patternCandidates: () => patternCandidates,
|
|
24
25
|
writeComponentGlobals: () => writeComponentGlobals
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(write_globals_exports);
|
|
@@ -136,7 +137,9 @@ var INTRINSICS = {
|
|
|
136
137
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
137
138
|
// dependency analysis must not guess at.
|
|
138
139
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
139
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
140
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
141
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
142
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
140
143
|
};
|
|
141
144
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
142
145
|
|
|
@@ -178,7 +181,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
178
181
|
builtins = true,
|
|
179
182
|
intrinsics = true,
|
|
180
183
|
generator = "@fluixi/compiler",
|
|
181
|
-
specifier = (module2) => module2
|
|
184
|
+
specifier = (module2) => module2,
|
|
185
|
+
candidates = []
|
|
182
186
|
} = options;
|
|
183
187
|
const all = [...rules];
|
|
184
188
|
if (builtins) {
|
|
@@ -190,7 +194,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
190
194
|
const shadowedByDom = [];
|
|
191
195
|
const unavailable = [];
|
|
192
196
|
const resolved = /* @__PURE__ */ new Map();
|
|
193
|
-
|
|
197
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
198
|
+
for (const name of [...names].sort()) {
|
|
194
199
|
const target = resolver.resolve(name);
|
|
195
200
|
if (!target) continue;
|
|
196
201
|
const pkg = packageOf(target.module);
|
|
@@ -201,7 +206,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
201
206
|
resolved.set(name, target);
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
|
-
const
|
|
209
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
210
|
+
const pkg = packageOf(i.module);
|
|
211
|
+
return !available || !pkg || available.has(pkg);
|
|
212
|
+
}) : [];
|
|
213
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
205
214
|
const modules = [
|
|
206
215
|
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
207
216
|
].sort();
|
|
@@ -221,15 +230,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
221
230
|
return `// import { ${n} } from '${module2 ? specifier(module2) : ""}';
|
|
222
231
|
`;
|
|
223
232
|
}).join("") : "";
|
|
224
|
-
const intrinsicLines =
|
|
233
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
225
234
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
226
|
-
)
|
|
235
|
+
);
|
|
227
236
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
228
|
-
const patternNote = patternRules
|
|
237
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
238
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
239
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
240
|
+
` : `//
|
|
229
241
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
230
242
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
231
243
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
232
|
-
|
|
244
|
+
`;
|
|
233
245
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
234
246
|
//
|
|
235
247
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -286,6 +298,30 @@ function projectDependencies(root) {
|
|
|
286
298
|
return void 0;
|
|
287
299
|
}
|
|
288
300
|
}
|
|
301
|
+
function patternCandidates(rules, root) {
|
|
302
|
+
const out = [];
|
|
303
|
+
for (const rule of rules) {
|
|
304
|
+
if (!("match" in rule) || !rule.module.startsWith("/")) continue;
|
|
305
|
+
const dir = (0, import_node_path.dirname)(rule.module);
|
|
306
|
+
const file = (0, import_node_path.basename)(rule.module);
|
|
307
|
+
const group = file.match(/\$\d+/);
|
|
308
|
+
if (dir.includes("$") || !group || file.indexOf("$", group.index + 1) !== -1) continue;
|
|
309
|
+
const before = file.slice(0, group.index);
|
|
310
|
+
const after = file.slice(group.index + group[0].length);
|
|
311
|
+
let entries;
|
|
312
|
+
try {
|
|
313
|
+
entries = (0, import_node_fs.readdirSync)((0, import_node_path.resolve)(root, dir.slice(1)));
|
|
314
|
+
} catch {
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
for (const entry of entries) {
|
|
318
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
319
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return out;
|
|
324
|
+
}
|
|
289
325
|
function writeComponentGlobals(options, root) {
|
|
290
326
|
if (options.globals === false) return { status: "skipped", reason: "disabled" };
|
|
291
327
|
const rules = options.resolve ?? [];
|
|
@@ -301,6 +337,7 @@ function writeComponentGlobals(options, root) {
|
|
|
301
337
|
}
|
|
302
338
|
const { source, declared } = componentGlobals(rules, {
|
|
303
339
|
available: projectDependencies(root),
|
|
340
|
+
candidates: patternCandidates(rules, root),
|
|
304
341
|
specifier: (module2) => forTypeScript(module2, (0, import_node_path.dirname)(target), root)
|
|
305
342
|
});
|
|
306
343
|
if (existing === source) {
|
|
@@ -26,5 +26,11 @@ export type WriteGlobalsOutcome = ({
|
|
|
26
26
|
*/
|
|
27
27
|
warning?: string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Names from the files a pattern rule points at: `/src/components/$1.tsx` lists
|
|
31
|
+
* `src/components` and offers each `X` for `X.tsx`. Only a project path with the group in
|
|
32
|
+
* the file name; the resolver still decides whether a name matches.
|
|
33
|
+
*/
|
|
34
|
+
export declare function patternCandidates(rules: readonly ComponentResolverRule[], root: string): string[];
|
|
29
35
|
/** Generate and write the declarations for `root`, returning what was done. */
|
|
30
36
|
export declare function writeComponentGlobals(options: WriteGlobalsOptions, root: string): WriteGlobalsOutcome;
|
|
@@ -26,6 +26,12 @@ export type WriteGlobalsOutcome = ({
|
|
|
26
26
|
*/
|
|
27
27
|
warning?: string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Names from the files a pattern rule points at: `/src/components/$1.tsx` lists
|
|
31
|
+
* `src/components` and offers each `X` for `X.tsx`. Only a project path with the group in
|
|
32
|
+
* the file name; the resolver still decides whether a name matches.
|
|
33
|
+
*/
|
|
34
|
+
export declare function patternCandidates(rules: readonly ComponentResolverRule[], root: string): string[];
|
|
29
35
|
/** Generate and write the declarations for `root`, returning what was done. */
|
|
30
36
|
export declare function writeComponentGlobals(options: WriteGlobalsOptions, root: string): WriteGlobalsOutcome;
|
|
31
37
|
//# sourceMappingURL=write-globals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/write-globals.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAC5E,GAAG;IACF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA2EF,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,MAAM,GACX,mBAAmB,
|
|
1
|
+
{"version":3,"file":"write-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/write-globals.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAC5E,GAAG;IACF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA2EF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,qBAAqB,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBjG;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,MAAM,GACX,mBAAmB,CAyCrB"}
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - **Only declare what the project can resolve.** Dependencies come from its manifest,
|
|
13
13
|
* so a component from an uninstalled package is skipped rather than degraded to `any`.
|
|
14
14
|
*/
|
|
15
|
-
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
-
import { dirname, relative, sep, resolve as resolvePath } from 'node:path';
|
|
15
|
+
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
+
import { basename, dirname, relative, sep, resolve as resolvePath } from 'node:path';
|
|
17
17
|
import { componentGlobals } from './component-globals.js';
|
|
18
18
|
/** The marker every generated file carries, used to tell ours from a hand-written one. */
|
|
19
19
|
const GENERATED_MARKER = 'GENERATED by @fluixi/compiler';
|
|
@@ -88,6 +88,38 @@ function projectDependencies(root) {
|
|
|
88
88
|
return undefined;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Names from the files a pattern rule points at: `/src/components/$1.tsx` lists
|
|
93
|
+
* `src/components` and offers each `X` for `X.tsx`. Only a project path with the group in
|
|
94
|
+
* the file name; the resolver still decides whether a name matches.
|
|
95
|
+
*/
|
|
96
|
+
export function patternCandidates(rules, root) {
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const rule of rules) {
|
|
99
|
+
if (!('match' in rule) || !rule.module.startsWith('/'))
|
|
100
|
+
continue;
|
|
101
|
+
const dir = dirname(rule.module);
|
|
102
|
+
const file = basename(rule.module);
|
|
103
|
+
const group = file.match(/\$\d+/);
|
|
104
|
+
if (dir.includes('$') || !group || file.indexOf('$', group.index + 1) !== -1)
|
|
105
|
+
continue;
|
|
106
|
+
const before = file.slice(0, group.index);
|
|
107
|
+
const after = file.slice(group.index + group[0].length);
|
|
108
|
+
let entries;
|
|
109
|
+
try {
|
|
110
|
+
entries = readdirSync(resolvePath(root, dir.slice(1)));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
117
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
91
123
|
/** Generate and write the declarations for `root`, returning what was done. */
|
|
92
124
|
export function writeComponentGlobals(options, root) {
|
|
93
125
|
if (options.globals === false)
|
|
@@ -106,6 +138,7 @@ export function writeComponentGlobals(options, root) {
|
|
|
106
138
|
}
|
|
107
139
|
const { source, declared } = componentGlobals(rules, {
|
|
108
140
|
available: projectDependencies(root),
|
|
141
|
+
candidates: patternCandidates(rules, root),
|
|
109
142
|
specifier: (module) => forTypeScript(module, dirname(target), root),
|
|
110
143
|
});
|
|
111
144
|
if (existing === source) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/resolve/write-globals.ts
|
|
2
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname, relative, sep, resolve as resolvePath } from "node:path";
|
|
2
|
+
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, relative, sep, resolve as resolvePath } from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/resolve/component-resolver.ts
|
|
6
6
|
var isMapRule = (rule) => "components" in rule;
|
|
@@ -111,7 +111,9 @@ var INTRINSICS = {
|
|
|
111
111
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
112
112
|
// dependency analysis must not guess at.
|
|
113
113
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
114
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
114
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
115
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
116
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
115
117
|
};
|
|
116
118
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
117
119
|
|
|
@@ -153,7 +155,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
153
155
|
builtins = true,
|
|
154
156
|
intrinsics = true,
|
|
155
157
|
generator = "@fluixi/compiler",
|
|
156
|
-
specifier = (module) => module
|
|
158
|
+
specifier = (module) => module,
|
|
159
|
+
candidates = []
|
|
157
160
|
} = options;
|
|
158
161
|
const all = [...rules];
|
|
159
162
|
if (builtins) {
|
|
@@ -165,7 +168,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
165
168
|
const shadowedByDom = [];
|
|
166
169
|
const unavailable = [];
|
|
167
170
|
const resolved = /* @__PURE__ */ new Map();
|
|
168
|
-
|
|
171
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
172
|
+
for (const name of [...names].sort()) {
|
|
169
173
|
const target = resolver.resolve(name);
|
|
170
174
|
if (!target) continue;
|
|
171
175
|
const pkg = packageOf(target.module);
|
|
@@ -176,7 +180,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
176
180
|
resolved.set(name, target);
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
|
-
const
|
|
183
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
184
|
+
const pkg = packageOf(i.module);
|
|
185
|
+
return !available || !pkg || available.has(pkg);
|
|
186
|
+
}) : [];
|
|
187
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
180
188
|
const modules = [
|
|
181
189
|
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
182
190
|
].sort();
|
|
@@ -196,15 +204,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
196
204
|
return `// import { ${n} } from '${module ? specifier(module) : ""}';
|
|
197
205
|
`;
|
|
198
206
|
}).join("") : "";
|
|
199
|
-
const intrinsicLines =
|
|
207
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
200
208
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
201
|
-
)
|
|
209
|
+
);
|
|
202
210
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
203
|
-
const patternNote = patternRules
|
|
211
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
212
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
213
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
214
|
+
` : `//
|
|
204
215
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
205
216
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
206
217
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
207
|
-
|
|
218
|
+
`;
|
|
208
219
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
209
220
|
//
|
|
210
221
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -261,6 +272,30 @@ function projectDependencies(root) {
|
|
|
261
272
|
return void 0;
|
|
262
273
|
}
|
|
263
274
|
}
|
|
275
|
+
function patternCandidates(rules, root) {
|
|
276
|
+
const out = [];
|
|
277
|
+
for (const rule of rules) {
|
|
278
|
+
if (!("match" in rule) || !rule.module.startsWith("/")) continue;
|
|
279
|
+
const dir = dirname(rule.module);
|
|
280
|
+
const file = basename(rule.module);
|
|
281
|
+
const group = file.match(/\$\d+/);
|
|
282
|
+
if (dir.includes("$") || !group || file.indexOf("$", group.index + 1) !== -1) continue;
|
|
283
|
+
const before = file.slice(0, group.index);
|
|
284
|
+
const after = file.slice(group.index + group[0].length);
|
|
285
|
+
let entries;
|
|
286
|
+
try {
|
|
287
|
+
entries = readdirSync(resolvePath(root, dir.slice(1)));
|
|
288
|
+
} catch {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
for (const entry of entries) {
|
|
292
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
293
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return out;
|
|
298
|
+
}
|
|
264
299
|
function writeComponentGlobals(options, root) {
|
|
265
300
|
if (options.globals === false) return { status: "skipped", reason: "disabled" };
|
|
266
301
|
const rules = options.resolve ?? [];
|
|
@@ -276,6 +311,7 @@ function writeComponentGlobals(options, root) {
|
|
|
276
311
|
}
|
|
277
312
|
const { source, declared } = componentGlobals(rules, {
|
|
278
313
|
available: projectDependencies(root),
|
|
314
|
+
candidates: patternCandidates(rules, root),
|
|
279
315
|
specifier: (module) => forTypeScript(module, dirname(target), root)
|
|
280
316
|
});
|
|
281
317
|
if (existing === source) {
|
|
@@ -302,5 +338,6 @@ function warnIfUnreachable(root, target) {
|
|
|
302
338
|
}
|
|
303
339
|
export {
|
|
304
340
|
DEFAULT_GLOBALS_PATH,
|
|
341
|
+
patternCandidates,
|
|
305
342
|
writeComponentGlobals
|
|
306
343
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
import {
|
|
3
3
|
MagicString
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DWNWN5RH.mjs";
|
|
5
5
|
import {
|
|
6
6
|
serverFnId
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-QZ4CJPYP.mjs";
|
|
8
|
+
import "./chunk-VOUI6XPV.mjs";
|
|
9
9
|
|
|
10
10
|
// src/transform/server-fns.ts
|
|
11
11
|
import { parse } from "@babel/parser";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
import {
|
|
3
3
|
serverFnId
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-QZ4CJPYP.mjs";
|
|
5
|
+
import "./chunk-VOUI6XPV.mjs";
|
|
6
6
|
|
|
7
7
|
// src/frontend/babel/server-functions.ts
|
|
8
8
|
import { transformSync } from "@babel/core";
|
package/dist/transform/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -498,7 +498,9 @@ var INTRINSICS = {
|
|
|
498
498
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
499
499
|
// dependency analysis must not guess at.
|
|
500
500
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
501
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
501
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
502
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
503
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
502
504
|
};
|
|
503
505
|
var RUNTIME_PRIMITIVES = {
|
|
504
506
|
signal: "signal-handle",
|
|
@@ -2358,10 +2360,34 @@ function collectIntrinsicEdits(program) {
|
|
|
2358
2360
|
});
|
|
2359
2361
|
return { edits, diagnostics, imports };
|
|
2360
2362
|
}
|
|
2363
|
+
function avoidBindingClashes(program, result, bound) {
|
|
2364
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
2365
|
+
for (const stmt of program.body ?? []) {
|
|
2366
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
2367
|
+
const module2 = stmt.source.value;
|
|
2368
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
2369
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
2370
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
2371
|
+
if (imported === spec.local.name && result.imports.get(module2)?.has(imported)) {
|
|
2372
|
+
importedAsIs.add(imported);
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
2377
|
+
for (const names of result.imports.values()) {
|
|
2378
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
2379
|
+
}
|
|
2380
|
+
if (!aliases.size) return;
|
|
2381
|
+
for (const edit of result.edits) {
|
|
2382
|
+
const alias = aliases.get(edit.code);
|
|
2383
|
+
if (alias) edit.code = alias;
|
|
2384
|
+
}
|
|
2385
|
+
result.aliases = aliases;
|
|
2386
|
+
}
|
|
2361
2387
|
function intrinsicImports(result, bound) {
|
|
2362
2388
|
const lines = [];
|
|
2363
2389
|
for (const [module2, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
2364
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
2390
|
+
const wanted = [...names].filter((name) => result.aliases?.has(name) || !bound.has(name)).sort().map((name) => result.aliases?.has(name) ? `${name} as ${result.aliases.get(name)}` : name);
|
|
2365
2391
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module2)};`);
|
|
2366
2392
|
}
|
|
2367
2393
|
return lines.length ? `${lines.join("\n")}
|
|
@@ -2561,6 +2587,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
2561
2587
|
});
|
|
2562
2588
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
2563
2589
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
2590
|
+
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
2564
2591
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
2565
2592
|
const silent = found.length === 0 && props.edits.length === 0 && sources.edits.length === 0 && intrinsics.edits.length === 0 && intrinsics.diagnostics.length === 0 && props.diagnostics.length === 0;
|
|
2566
2593
|
if (silent) return null;
|
package/dist/transform/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.92 | (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";
|
|
@@ -1530,7 +1530,9 @@ var INTRINSICS = {
|
|
|
1530
1530
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
1531
1531
|
// dependency analysis must not guess at.
|
|
1532
1532
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
1533
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
1533
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
1534
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
1535
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
1534
1536
|
};
|
|
1535
1537
|
var RUNTIME_PRIMITIVES = {
|
|
1536
1538
|
signal: "signal-handle",
|
|
@@ -3391,10 +3393,34 @@ function collectIntrinsicEdits(program) {
|
|
|
3391
3393
|
});
|
|
3392
3394
|
return { edits, diagnostics, imports };
|
|
3393
3395
|
}
|
|
3396
|
+
function avoidBindingClashes(program, result, bound) {
|
|
3397
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
3398
|
+
for (const stmt of program.body ?? []) {
|
|
3399
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
3400
|
+
const module = stmt.source.value;
|
|
3401
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
3402
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
3403
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
3404
|
+
if (imported === spec.local.name && result.imports.get(module)?.has(imported)) {
|
|
3405
|
+
importedAsIs.add(imported);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
3410
|
+
for (const names of result.imports.values()) {
|
|
3411
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
3412
|
+
}
|
|
3413
|
+
if (!aliases.size) return;
|
|
3414
|
+
for (const edit of result.edits) {
|
|
3415
|
+
const alias = aliases.get(edit.code);
|
|
3416
|
+
if (alias) edit.code = alias;
|
|
3417
|
+
}
|
|
3418
|
+
result.aliases = aliases;
|
|
3419
|
+
}
|
|
3394
3420
|
function intrinsicImports(result, bound) {
|
|
3395
3421
|
const lines = [];
|
|
3396
3422
|
for (const [module, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
3397
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
3423
|
+
const wanted = [...names].filter((name) => result.aliases?.has(name) || !bound.has(name)).sort().map((name) => result.aliases?.has(name) ? `${name} as ${result.aliases.get(name)}` : name);
|
|
3398
3424
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module)};`);
|
|
3399
3425
|
}
|
|
3400
3426
|
return lines.length ? `${lines.join("\n")}
|
|
@@ -3594,6 +3620,7 @@ function transformTemplates(code, id, options = {}) {
|
|
|
3594
3620
|
});
|
|
3595
3621
|
const props = options.propsDestructure === false ? { edits: [], diagnostics: [], used: /* @__PURE__ */ new Set() } : collectPropsEdits(ast.program, code, { runtimeModule: options.runtimeModule });
|
|
3596
3622
|
const intrinsics = options.intrinsics === false ? { edits: [], diagnostics: [], imports: /* @__PURE__ */ new Map() } : collectIntrinsicEdits(ast.program);
|
|
3623
|
+
if (intrinsics.edits.length) avoidBindingClashes(ast.program, intrinsics, moduleBindings(ast.program));
|
|
3597
3624
|
const sources = options.sourceLocations === true ? collectSourceEdits(ast.program, sourceName) : { edits: [], marked: 0 };
|
|
3598
3625
|
const silent = found.length === 0 && props.edits.length === 0 && sources.edits.length === 0 && intrinsics.edits.length === 0 && intrinsics.diagnostics.length === 0 && props.diagnostics.length === 0;
|
|
3599
3626
|
if (silent) return null;
|
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/transform/intrinsics.ts
|
|
21
21
|
var intrinsics_exports = {};
|
|
22
22
|
__export(intrinsics_exports, {
|
|
23
|
+
avoidBindingClashes: () => avoidBindingClashes,
|
|
23
24
|
collectIntrinsicEdits: () => collectIntrinsicEdits,
|
|
24
25
|
intrinsicImports: () => intrinsicImports
|
|
25
26
|
});
|
|
@@ -42,7 +43,9 @@ var INTRINSICS = {
|
|
|
42
43
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
43
44
|
// dependency analysis must not guess at.
|
|
44
45
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
45
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
46
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
47
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
48
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
46
49
|
};
|
|
47
50
|
var RUNTIME_PRIMITIVES = {
|
|
48
51
|
signal: "signal-handle",
|
|
@@ -205,10 +208,34 @@ function collectIntrinsicEdits(program) {
|
|
|
205
208
|
});
|
|
206
209
|
return { edits, diagnostics, imports };
|
|
207
210
|
}
|
|
211
|
+
function avoidBindingClashes(program, result, bound) {
|
|
212
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
213
|
+
for (const stmt of program.body ?? []) {
|
|
214
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
215
|
+
const module2 = stmt.source.value;
|
|
216
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
217
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
218
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
219
|
+
if (imported === spec.local.name && result.imports.get(module2)?.has(imported)) {
|
|
220
|
+
importedAsIs.add(imported);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
225
|
+
for (const names of result.imports.values()) {
|
|
226
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
227
|
+
}
|
|
228
|
+
if (!aliases.size) return;
|
|
229
|
+
for (const edit of result.edits) {
|
|
230
|
+
const alias = aliases.get(edit.code);
|
|
231
|
+
if (alias) edit.code = alias;
|
|
232
|
+
}
|
|
233
|
+
result.aliases = aliases;
|
|
234
|
+
}
|
|
208
235
|
function intrinsicImports(result, bound) {
|
|
209
236
|
const lines = [];
|
|
210
237
|
for (const [module2, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
211
|
-
const wanted = [...names].filter((name) => !bound.has(name)).sort();
|
|
238
|
+
const wanted = [...names].filter((name) => result.aliases?.has(name) || !bound.has(name)).sort().map((name) => result.aliases?.has(name) ? `${name} as ${result.aliases.get(name)}` : name);
|
|
212
239
|
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module2)};`);
|
|
213
240
|
}
|
|
214
241
|
return lines.length ? `${lines.join("\n")}
|
|
@@ -14,8 +14,20 @@ export interface IntrinsicsResult {
|
|
|
14
14
|
diagnostics: IntrinsicDiagnostic[];
|
|
15
15
|
/** Runtime exports the rewritten code needs, by module. */
|
|
16
16
|
imports: Map<string, Set<string>>;
|
|
17
|
+
/** Runtime exports imported under another name, because the module binds theirs. */
|
|
18
|
+
aliases?: Map<string, string>;
|
|
17
19
|
}
|
|
18
20
|
/** Find the `$` calls in a module and say what they compile to. */
|
|
19
21
|
export declare function collectIntrinsicEdits(program: unknown): IntrinsicsResult;
|
|
22
|
+
/**
|
|
23
|
+
* Point a rewritten call past a local binding of the same name.
|
|
24
|
+
*
|
|
25
|
+
* `$env('X')` becomes `env('X')`, and the import of `env` used to be skipped when the module
|
|
26
|
+
* already bound `env`, on the assumption that it was the same import. A config module with its
|
|
27
|
+
* own `const env = {…}` is common, and there the call reached the app's object instead. Such a
|
|
28
|
+
* name is now imported under a private alias. A module that imports that very export from that
|
|
29
|
+
* very module keeps the old behaviour: the binding is the runtime already.
|
|
30
|
+
*/
|
|
31
|
+
export declare function avoidBindingClashes(program: unknown, result: IntrinsicsResult, bound: Set<string>): void;
|
|
20
32
|
/** The import statements a result needs, minus anything the module already binds. */
|
|
21
33
|
export declare function intrinsicImports(result: IntrinsicsResult, bound: Set<string>): string;
|
|
@@ -14,9 +14,21 @@ export interface IntrinsicsResult {
|
|
|
14
14
|
diagnostics: IntrinsicDiagnostic[];
|
|
15
15
|
/** Runtime exports the rewritten code needs, by module. */
|
|
16
16
|
imports: Map<string, Set<string>>;
|
|
17
|
+
/** Runtime exports imported under another name, because the module binds theirs. */
|
|
18
|
+
aliases?: Map<string, string>;
|
|
17
19
|
}
|
|
18
20
|
/** Find the `$` calls in a module and say what they compile to. */
|
|
19
21
|
export declare function collectIntrinsicEdits(program: unknown): IntrinsicsResult;
|
|
22
|
+
/**
|
|
23
|
+
* Point a rewritten call past a local binding of the same name.
|
|
24
|
+
*
|
|
25
|
+
* `$env('X')` becomes `env('X')`, and the import of `env` used to be skipped when the module
|
|
26
|
+
* already bound `env`, on the assumption that it was the same import. A config module with its
|
|
27
|
+
* own `const env = {…}` is common, and there the call reached the app's object instead. Such a
|
|
28
|
+
* name is now imported under a private alias. A module that imports that very export from that
|
|
29
|
+
* very module keeps the old behaviour: the binding is the runtime already.
|
|
30
|
+
*/
|
|
31
|
+
export declare function avoidBindingClashes(program: unknown, result: IntrinsicsResult, bound: Set<string>): void;
|
|
20
32
|
/** The import statements a result needs, minus anything the module already binds. */
|
|
21
33
|
export declare function intrinsicImports(result: IntrinsicsResult, bound: Set<string>): string;
|
|
22
34
|
//# sourceMappingURL=intrinsics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intrinsics.d.ts","sourceRoot":"","sources":["../../src/transform/intrinsics.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,2DAA2D;IAC3D,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"intrinsics.d.ts","sourceRoot":"","sources":["../../src/transform/intrinsics.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,2DAA2D;IAC3D,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,oFAAoF;IACpF,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAaD,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAuCxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAwBxG;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAUrF"}
|
|
@@ -66,11 +66,53 @@ export function collectIntrinsicEdits(program) {
|
|
|
66
66
|
});
|
|
67
67
|
return { edits, diagnostics, imports };
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Point a rewritten call past a local binding of the same name.
|
|
71
|
+
*
|
|
72
|
+
* `$env('X')` becomes `env('X')`, and the import of `env` used to be skipped when the module
|
|
73
|
+
* already bound `env`, on the assumption that it was the same import. A config module with its
|
|
74
|
+
* own `const env = {…}` is common, and there the call reached the app's object instead. Such a
|
|
75
|
+
* name is now imported under a private alias. A module that imports that very export from that
|
|
76
|
+
* very module keeps the old behaviour: the binding is the runtime already.
|
|
77
|
+
*/
|
|
78
|
+
export function avoidBindingClashes(program, result, bound) {
|
|
79
|
+
const importedAsIs = new Set();
|
|
80
|
+
for (const stmt of program.body ?? []) {
|
|
81
|
+
if (stmt.type !== 'ImportDeclaration')
|
|
82
|
+
continue;
|
|
83
|
+
const module = stmt.source.value;
|
|
84
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
85
|
+
if (spec.type !== 'ImportSpecifier')
|
|
86
|
+
continue;
|
|
87
|
+
const imported = (spec.imported.name ?? spec.imported.value);
|
|
88
|
+
if (imported === spec.local.name && result.imports.get(module)?.has(imported)) {
|
|
89
|
+
importedAsIs.add(imported);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const aliases = new Map();
|
|
94
|
+
for (const names of result.imports.values()) {
|
|
95
|
+
for (const name of names)
|
|
96
|
+
if (bound.has(name) && !importedAsIs.has(name))
|
|
97
|
+
aliases.set(name, `__fx_${name}`);
|
|
98
|
+
}
|
|
99
|
+
if (!aliases.size)
|
|
100
|
+
return;
|
|
101
|
+
for (const edit of result.edits) {
|
|
102
|
+
const alias = aliases.get(edit.code);
|
|
103
|
+
if (alias)
|
|
104
|
+
edit.code = alias;
|
|
105
|
+
}
|
|
106
|
+
result.aliases = aliases;
|
|
107
|
+
}
|
|
69
108
|
/** The import statements a result needs, minus anything the module already binds. */
|
|
70
109
|
export function intrinsicImports(result, bound) {
|
|
71
110
|
const lines = [];
|
|
72
111
|
for (const [module, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
73
|
-
const wanted = [...names]
|
|
112
|
+
const wanted = [...names]
|
|
113
|
+
.filter((name) => result.aliases?.has(name) || !bound.has(name))
|
|
114
|
+
.sort()
|
|
115
|
+
.map((name) => (result.aliases?.has(name) ? `${name} as ${result.aliases.get(name)}` : name));
|
|
74
116
|
if (wanted.length)
|
|
75
117
|
lines.push(`import { ${wanted.join(', ')} } from ${JSON.stringify(module)};`);
|
|
76
118
|
}
|