@fluixi/compiler 1.0.0-alpha.100
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/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/analyze/expr-shape.cjs +62 -0
- package/dist/analyze/expr-shape.d.cts +14 -0
- package/dist/analyze/expr-shape.d.ts +15 -0
- package/dist/analyze/expr-shape.d.ts.map +1 -0
- package/dist/analyze/expr-shape.js +37 -0
- package/dist/analyze/expr-shape.mjs +41 -0
- package/dist/analyze/intrinsics.cjs +112 -0
- package/dist/analyze/intrinsics.d.cts +80 -0
- package/dist/analyze/intrinsics.d.ts +81 -0
- package/dist/analyze/intrinsics.d.ts.map +1 -0
- package/dist/analyze/intrinsics.js +126 -0
- package/dist/analyze/intrinsics.mjs +91 -0
- package/dist/analyze/paren.cjs +134 -0
- package/dist/analyze/paren.d.cts +23 -0
- package/dist/analyze/paren.d.ts +24 -0
- package/dist/analyze/paren.d.ts.map +1 -0
- package/dist/analyze/paren.js +168 -0
- package/dist/analyze/paren.mjs +113 -0
- package/dist/analyze/props-destructure.cjs +226 -0
- package/dist/analyze/props-destructure.d.cts +83 -0
- package/dist/analyze/props-destructure.d.ts +84 -0
- package/dist/analyze/props-destructure.d.ts.map +1 -0
- package/dist/analyze/props-destructure.js +272 -0
- package/dist/analyze/props-destructure.mjs +205 -0
- package/dist/analyze/reactive-bindings.cjs +210 -0
- package/dist/analyze/reactive-bindings.d.cts +42 -0
- package/dist/analyze/reactive-bindings.d.ts +43 -0
- package/dist/analyze/reactive-bindings.d.ts.map +1 -0
- package/dist/analyze/reactive-bindings.js +191 -0
- package/dist/analyze/reactive-bindings.mjs +187 -0
- package/dist/analyze/reactive-expr.cjs +38 -0
- package/dist/analyze/reactive-expr.d.cts +38 -0
- package/dist/analyze/reactive-expr.d.ts +39 -0
- package/dist/analyze/reactive-expr.d.ts.map +1 -0
- package/dist/analyze/reactive-expr.js +31 -0
- package/dist/analyze/reactive-expr.mjs +17 -0
- package/dist/analyze/static-graph.cjs +831 -0
- package/dist/analyze/static-graph.d.cts +102 -0
- package/dist/analyze/static-graph.d.ts +103 -0
- package/dist/analyze/static-graph.d.ts.map +1 -0
- package/dist/analyze/static-graph.js +871 -0
- package/dist/analyze/static-graph.mjs +813 -0
- package/dist/babel-I6BUWUCU.mjs +636 -0
- package/dist/chunk-3AICWNF7.mjs +92 -0
- package/dist/chunk-6CWJWGE2.mjs +2170 -0
- package/dist/chunk-C3XPDB4Y.mjs +16 -0
- package/dist/chunk-GX5XV6Z7.mjs +190 -0
- package/dist/chunk-HXEXPWJ2.mjs +999 -0
- package/dist/chunk-NU3W67UZ.mjs +584 -0
- package/dist/chunk-SKAVY75W.mjs +11 -0
- package/dist/codegen/backend.cjs +18 -0
- package/dist/codegen/backend.d.cts +35 -0
- package/dist/codegen/backend.d.ts +36 -0
- package/dist/codegen/backend.d.ts.map +1 -0
- package/dist/codegen/backend.js +1 -0
- package/dist/codegen/backend.mjs +0 -0
- package/dist/codegen/backends/imperative.cjs +577 -0
- package/dist/codegen/backends/imperative.d.cts +11 -0
- package/dist/codegen/backends/imperative.d.ts +12 -0
- package/dist/codegen/backends/imperative.d.ts.map +1 -0
- package/dist/codegen/backends/imperative.js +362 -0
- package/dist/codegen/backends/imperative.mjs +554 -0
- package/dist/codegen/contract.cjs +52 -0
- package/dist/codegen/contract.d.cts +24 -0
- package/dist/codegen/contract.d.ts +25 -0
- package/dist/codegen/contract.d.ts.map +1 -0
- package/dist/codegen/contract.js +30 -0
- package/dist/codegen/contract.mjs +31 -0
- package/dist/codegen/partial-template.cjs +176 -0
- package/dist/codegen/partial-template.d.cts +61 -0
- package/dist/codegen/partial-template.d.ts +62 -0
- package/dist/codegen/partial-template.d.ts.map +1 -0
- package/dist/codegen/partial-template.js +0 -0
- package/dist/codegen/partial-template.mjs +153 -0
- package/dist/codegen/serialize-static.cjs +125 -0
- package/dist/codegen/serialize-static.d.cts +38 -0
- package/dist/codegen/serialize-static.d.ts +39 -0
- package/dist/codegen/serialize-static.d.ts.map +1 -0
- package/dist/codegen/serialize-static.js +165 -0
- package/dist/codegen/serialize-static.mjs +104 -0
- package/dist/frontend/babel/build-ir-lit.cjs +1933 -0
- package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
- package/dist/frontend/babel/build-ir-lit.d.ts +27 -0
- package/dist/frontend/babel/build-ir-lit.d.ts.map +1 -0
- package/dist/frontend/babel/build-ir-lit.js +13 -0
- package/dist/frontend/babel/build-ir-lit.mjs +1902 -0
- package/dist/frontend/babel/build-ir.cjs +1948 -0
- package/dist/frontend/babel/build-ir.d.cts +35 -0
- package/dist/frontend/babel/build-ir.d.ts +36 -0
- package/dist/frontend/babel/build-ir.d.ts.map +1 -0
- package/dist/frontend/babel/build-ir.js +124 -0
- package/dist/frontend/babel/build-ir.mjs +1919 -0
- package/dist/frontend/babel/index.cjs +2610 -0
- package/dist/frontend/babel/index.d.cts +33 -0
- package/dist/frontend/babel/index.d.ts +34 -0
- package/dist/frontend/babel/index.d.ts.map +1 -0
- package/dist/frontend/babel/index.js +65 -0
- package/dist/frontend/babel/index.mjs +2580 -0
- package/dist/frontend/babel/lower-template.cjs +1931 -0
- package/dist/frontend/babel/lower-template.d.cts +23 -0
- package/dist/frontend/babel/lower-template.d.ts +24 -0
- package/dist/frontend/babel/lower-template.d.ts.map +1 -0
- package/dist/frontend/babel/lower-template.js +64 -0
- package/dist/frontend/babel/lower-template.mjs +1902 -0
- package/dist/frontend/babel/plugin.cjs +2556 -0
- package/dist/frontend/babel/plugin.d.cts +95 -0
- package/dist/frontend/babel/plugin.d.ts +96 -0
- package/dist/frontend/babel/plugin.d.ts.map +1 -0
- package/dist/frontend/babel/plugin.js +523 -0
- package/dist/frontend/babel/plugin.mjs +2527 -0
- package/dist/frontend/babel/server-functions.cjs +110 -0
- package/dist/frontend/babel/server-functions.d.cts +10 -0
- package/dist/frontend/babel/server-functions.d.ts +11 -0
- package/dist/frontend/babel/server-functions.d.ts.map +1 -0
- package/dist/frontend/babel/server-functions.js +81 -0
- package/dist/frontend/babel/server-functions.mjs +89 -0
- package/dist/frontend/babel/types.cjs +18 -0
- package/dist/frontend/babel/types.d.cts +33 -0
- package/dist/frontend/babel/types.d.ts +34 -0
- package/dist/frontend/babel/types.d.ts.map +1 -0
- package/dist/frontend/babel/types.js +1 -0
- package/dist/frontend/babel/types.mjs +0 -0
- package/dist/frontend/types.cjs +18 -0
- package/dist/frontend/types.d.cts +25 -0
- package/dist/frontend/types.d.ts +26 -0
- package/dist/frontend/types.d.ts.map +1 -0
- package/dist/frontend/types.js +1 -0
- package/dist/frontend/types.mjs +0 -0
- package/dist/frontend/vocabulary.cjs +98 -0
- package/dist/frontend/vocabulary.d.cts +79 -0
- package/dist/frontend/vocabulary.d.ts +80 -0
- package/dist/frontend/vocabulary.d.ts.map +1 -0
- package/dist/frontend/vocabulary.js +124 -0
- package/dist/frontend/vocabulary.mjs +77 -0
- package/dist/index.cjs +1957 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.mjs +1949 -0
- package/dist/integrations.cjs +5705 -0
- package/dist/integrations.d.cts +215 -0
- package/dist/integrations.d.ts +216 -0
- package/dist/integrations.d.ts.map +1 -0
- package/dist/integrations.js +566 -0
- package/dist/integrations.mjs +810 -0
- package/dist/ir/nodes.cjs +18 -0
- package/dist/ir/nodes.d.cts +168 -0
- package/dist/ir/nodes.d.ts +169 -0
- package/dist/ir/nodes.d.ts.map +1 -0
- package/dist/ir/nodes.js +1 -0
- package/dist/ir/nodes.mjs +0 -0
- package/dist/lower/compile-template.cjs +1670 -0
- package/dist/lower/compile-template.d.cts +82 -0
- package/dist/lower/compile-template.d.ts +83 -0
- package/dist/lower/compile-template.d.ts.map +1 -0
- package/dist/lower/compile-template.js +79 -0
- package/dist/lower/compile-template.mjs +1662 -0
- package/dist/lower/entities.cjs +288 -0
- package/dist/lower/entities.d.cts +1 -0
- package/dist/lower/entities.d.ts +2 -0
- package/dist/lower/entities.d.ts.map +1 -0
- package/dist/lower/entities.js +54 -0
- package/dist/lower/entities.mjs +267 -0
- package/dist/lower/jsx.cjs +1101 -0
- package/dist/lower/jsx.d.cts +33 -0
- package/dist/lower/jsx.d.ts +34 -0
- package/dist/lower/jsx.d.ts.map +1 -0
- package/dist/lower/jsx.js +414 -0
- package/dist/lower/jsx.mjs +1078 -0
- package/dist/lower/template.cjs +1354 -0
- package/dist/lower/template.d.cts +53 -0
- package/dist/lower/template.d.ts +54 -0
- package/dist/lower/template.d.ts.map +1 -0
- package/dist/lower/template.js +542 -0
- package/dist/lower/template.mjs +1335 -0
- package/dist/lower/text.cjs +42 -0
- package/dist/lower/text.d.cts +10 -0
- package/dist/lower/text.d.ts +11 -0
- package/dist/lower/text.d.ts.map +1 -0
- package/dist/lower/text.js +31 -0
- package/dist/lower/text.mjs +21 -0
- package/dist/optimize/analyze-static.cjs +112 -0
- package/dist/optimize/analyze-static.d.cts +39 -0
- package/dist/optimize/analyze-static.d.ts +40 -0
- package/dist/optimize/analyze-static.d.ts.map +1 -0
- package/dist/optimize/analyze-static.js +131 -0
- package/dist/optimize/analyze-static.mjs +91 -0
- package/dist/optimize/collapse-strategies.cjs +90 -0
- package/dist/optimize/collapse-strategies.d.cts +30 -0
- package/dist/optimize/collapse-strategies.d.ts +31 -0
- package/dist/optimize/collapse-strategies.d.ts.map +1 -0
- package/dist/optimize/collapse-strategies.js +33 -0
- package/dist/optimize/collapse-strategies.mjs +67 -0
- package/dist/options.cjs +33 -0
- package/dist/options.d.cts +39 -0
- package/dist/options.d.ts +40 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +8 -0
- package/dist/options.mjs +12 -0
- package/dist/resolve/builtins.cjs +73 -0
- package/dist/resolve/builtins.d.cts +68 -0
- package/dist/resolve/builtins.d.ts +69 -0
- package/dist/resolve/builtins.d.ts.map +1 -0
- package/dist/resolve/builtins.js +64 -0
- package/dist/resolve/builtins.mjs +53 -0
- package/dist/resolve/component-globals.cjs +272 -0
- package/dist/resolve/component-globals.d.cts +88 -0
- package/dist/resolve/component-globals.d.ts +89 -0
- package/dist/resolve/component-globals.d.ts.map +1 -0
- package/dist/resolve/component-globals.js +160 -0
- package/dist/resolve/component-globals.mjs +249 -0
- package/dist/resolve/component-resolver.cjs +80 -0
- package/dist/resolve/component-resolver.d.cts +68 -0
- package/dist/resolve/component-resolver.d.ts +69 -0
- package/dist/resolve/component-resolver.d.ts.map +1 -0
- package/dist/resolve/component-resolver.js +95 -0
- package/dist/resolve/component-resolver.mjs +59 -0
- package/dist/resolve/load-directive.cjs +93 -0
- package/dist/resolve/load-directive.d.cts +53 -0
- package/dist/resolve/load-directive.d.ts +54 -0
- package/dist/resolve/load-directive.d.ts.map +1 -0
- package/dist/resolve/load-directive.js +93 -0
- package/dist/resolve/load-directive.mjs +72 -0
- package/dist/resolve/resolve-ir.cjs +108 -0
- package/dist/resolve/resolve-ir.d.cts +53 -0
- package/dist/resolve/resolve-ir.d.ts +54 -0
- package/dist/resolve/resolve-ir.d.ts.map +1 -0
- package/dist/resolve/resolve-ir.js +58 -0
- package/dist/resolve/resolve-ir.mjs +85 -0
- package/dist/resolve/write-globals.cjs +383 -0
- package/dist/resolve/write-globals.d.cts +36 -0
- package/dist/resolve/write-globals.d.ts +37 -0
- package/dist/resolve/write-globals.d.ts.map +1 -0
- package/dist/resolve/write-globals.js +169 -0
- package/dist/resolve/write-globals.mjs +362 -0
- package/dist/server-fns-VZLHMQTC.mjs +79 -0
- package/dist/server-functions-UAZKOLZW.mjs +82 -0
- package/dist/transform/bindings.cjs +71 -0
- package/dist/transform/bindings.d.cts +16 -0
- package/dist/transform/bindings.d.ts +17 -0
- package/dist/transform/bindings.d.ts.map +1 -0
- package/dist/transform/bindings.js +69 -0
- package/dist/transform/bindings.mjs +50 -0
- package/dist/transform/index.cjs +3837 -0
- package/dist/transform/index.d.cts +15 -0
- package/dist/transform/index.d.ts +16 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +12 -0
- package/dist/transform/index.mjs +4882 -0
- package/dist/transform/intrinsics.cjs +261 -0
- package/dist/transform/intrinsics.d.cts +33 -0
- package/dist/transform/intrinsics.d.ts +34 -0
- package/dist/transform/intrinsics.d.ts.map +1 -0
- package/dist/transform/intrinsics.js +120 -0
- package/dist/transform/intrinsics.mjs +238 -0
- package/dist/transform/props.cjs +441 -0
- package/dist/transform/props.d.cts +45 -0
- package/dist/transform/props.d.ts +46 -0
- package/dist/transform/props.d.ts.map +1 -0
- package/dist/transform/props.js +221 -0
- package/dist/transform/props.mjs +1487 -0
- package/dist/transform/server-fn-id.cjs +35 -0
- package/dist/transform/server-fn-id.d.cts +9 -0
- package/dist/transform/server-fn-id.d.ts +10 -0
- package/dist/transform/server-fn-id.d.ts.map +1 -0
- package/dist/transform/server-fn-id.js +18 -0
- package/dist/transform/server-fn-id.mjs +14 -0
- package/dist/transform/server-fns.cjs +114 -0
- package/dist/transform/server-fns.d.cts +12 -0
- package/dist/transform/server-fns.d.ts +13 -0
- package/dist/transform/server-fns.d.ts.map +1 -0
- package/dist/transform/server-fns.js +94 -0
- package/dist/transform/server-fns.mjs +1160 -0
- package/dist/transform/source-locations.cjs +393 -0
- package/dist/transform/source-locations.d.cts +48 -0
- package/dist/transform/source-locations.d.ts +49 -0
- package/dist/transform/source-locations.d.ts.map +1 -0
- package/dist/transform/source-locations.js +303 -0
- package/dist/transform/source-locations.mjs +370 -0
- package/dist/transform/styles.cjs +606 -0
- package/dist/transform/styles.d.cts +237 -0
- package/dist/transform/styles.d.ts +238 -0
- package/dist/transform/styles.d.ts.map +1 -0
- package/dist/transform/styles.js +743 -0
- package/dist/transform/styles.mjs +671 -0
- package/dist/transform/templates.cjs +3806 -0
- package/dist/transform/templates.d.cts +82 -0
- package/dist/transform/templates.d.ts +83 -0
- package/dist/transform/templates.d.ts.map +1 -0
- package/dist/transform/templates.js +613 -0
- package/dist/transform/templates.mjs +4852 -0
- package/dist/transform-3W45L3EA.mjs +951 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/vite-styles.cjs +223 -0
- package/dist/vite-styles.d.cts +68 -0
- package/dist/vite-styles.d.ts +69 -0
- package/dist/vite-styles.d.ts.map +1 -0
- package/dist/vite-styles.js +241 -0
- package/dist/vite-styles.mjs +214 -0
- package/package.json +141 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// src/analyze/intrinsics.ts
|
|
2
|
+
var REACTIVE_MODULE = "@fluixi/reactive/signal";
|
|
3
|
+
var INTRINSICS = {
|
|
4
|
+
$signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
|
|
5
|
+
$memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
|
|
6
|
+
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
7
|
+
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
8
|
+
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
9
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
10
|
+
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
11
|
+
// name. Still worth having: no import to write, and when a shorter form is
|
|
12
|
+
// designed, the change is this line rather than a compiler pass.
|
|
13
|
+
$selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
14
|
+
$deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
15
|
+
// Not value constructors, but the compiler has to know them: they change what a read
|
|
16
|
+
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
17
|
+
// dependency analysis must not guess at.
|
|
18
|
+
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
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" },
|
|
33
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
34
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
35
|
+
};
|
|
36
|
+
var RUNTIME_PRIMITIVES = {
|
|
37
|
+
signal: "signal-handle",
|
|
38
|
+
memo: "memo-handle",
|
|
39
|
+
effect: "effect",
|
|
40
|
+
store: "store-handle",
|
|
41
|
+
createSignal: ["signal-accessor", "signal-setter"],
|
|
42
|
+
createMemo: "memo-accessor",
|
|
43
|
+
createEffect: "effect",
|
|
44
|
+
createRenderEffect: "effect",
|
|
45
|
+
renderEffect: "effect",
|
|
46
|
+
computed: "effect",
|
|
47
|
+
createStore: "reactive-object",
|
|
48
|
+
resource: "resource-handle",
|
|
49
|
+
cachedResource: "resource-handle",
|
|
50
|
+
createResource: "reactive-object",
|
|
51
|
+
createSelector: "memo-accessor",
|
|
52
|
+
createDeferred: "memo-accessor"
|
|
53
|
+
};
|
|
54
|
+
var PRIMITIVE_MODULES = [
|
|
55
|
+
"@fluixi/reactive",
|
|
56
|
+
"@fluixi/reactive/signal",
|
|
57
|
+
"@fluixi/reactive/store",
|
|
58
|
+
"@fluixi/reactive/cached-resource",
|
|
59
|
+
"@fluixi/core"
|
|
60
|
+
];
|
|
61
|
+
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
62
|
+
function isIntrinsicName(name) {
|
|
63
|
+
return Object.prototype.hasOwnProperty.call(INTRINSICS, name);
|
|
64
|
+
}
|
|
65
|
+
function isPrimitiveModule(source) {
|
|
66
|
+
return PRIMITIVE_MODULES.includes(source);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/analyze/reactive-bindings.ts
|
|
70
|
+
function patternNames(node, out) {
|
|
71
|
+
if (!node) return;
|
|
72
|
+
switch (node.type) {
|
|
73
|
+
case "Identifier":
|
|
74
|
+
out.add(node.name);
|
|
75
|
+
return;
|
|
76
|
+
case "ObjectPattern":
|
|
77
|
+
for (const p of node.properties ?? []) {
|
|
78
|
+
if (p.type === "RestElement") patternNames(p.argument, out);
|
|
79
|
+
else patternNames(p.value, out);
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
case "ArrayPattern":
|
|
83
|
+
for (const e of node.elements ?? []) patternNames(e, out);
|
|
84
|
+
return;
|
|
85
|
+
case "AssignmentPattern":
|
|
86
|
+
patternNames(node.left, out);
|
|
87
|
+
return;
|
|
88
|
+
case "RestElement":
|
|
89
|
+
patternNames(node.argument, out);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function walk(root, visit) {
|
|
94
|
+
if (!root || typeof root !== "object" || typeof root.type !== "string") return;
|
|
95
|
+
visit(root);
|
|
96
|
+
for (const key of Object.keys(root)) {
|
|
97
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
|
|
98
|
+
const value = root[key];
|
|
99
|
+
if (Array.isArray(value)) for (const item of value) walk(item, visit);
|
|
100
|
+
else if (value && typeof value === "object") walk(value, visit);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function calledPrimitive(node, bindings) {
|
|
104
|
+
if (node.type !== "CallExpression") return void 0;
|
|
105
|
+
const callee = node.callee;
|
|
106
|
+
if (callee?.type !== "Identifier") return void 0;
|
|
107
|
+
const name = callee.name;
|
|
108
|
+
const imported = bindings.primitives.get(name);
|
|
109
|
+
if (imported) return imported;
|
|
110
|
+
const intrinsic = INTRINSICS[name];
|
|
111
|
+
if (intrinsic && !bindings.shadowed.has(name)) return intrinsic.returns;
|
|
112
|
+
return void 0;
|
|
113
|
+
}
|
|
114
|
+
function classify(id, returns, kinds) {
|
|
115
|
+
if (Array.isArray(returns)) {
|
|
116
|
+
if (id.type === "ArrayPattern") {
|
|
117
|
+
id.elements.forEach((element, index) => {
|
|
118
|
+
const kind = returns[index];
|
|
119
|
+
if (element?.type === "Identifier" && kind) kinds.set(element.name, kind);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (id.type === "Identifier") kinds.set(id.name, returns);
|
|
125
|
+
}
|
|
126
|
+
function resolveReactiveBindings(program) {
|
|
127
|
+
const bindings = { kinds: /* @__PURE__ */ new Map(), primitives: /* @__PURE__ */ new Map(), shadowed: /* @__PURE__ */ new Set() };
|
|
128
|
+
const root = program;
|
|
129
|
+
walk(root, (node) => {
|
|
130
|
+
const names = /* @__PURE__ */ new Set();
|
|
131
|
+
if (node.type === "VariableDeclarator") patternNames(node.id, names);
|
|
132
|
+
else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") patternNames(node.id, names);
|
|
133
|
+
else if (node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier") patternNames(node.local, names);
|
|
134
|
+
else if (node.type === "ImportSpecifier") patternNames(node.local, names);
|
|
135
|
+
else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration") {
|
|
136
|
+
for (const p of node.params ?? []) patternNames(p, names);
|
|
137
|
+
}
|
|
138
|
+
for (const name of names) if (INTRINSICS[name]) bindings.shadowed.add(name);
|
|
139
|
+
});
|
|
140
|
+
for (const statement of root.body ?? []) {
|
|
141
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
142
|
+
if (!isPrimitiveModule(statement.source?.value)) continue;
|
|
143
|
+
for (const specifier of statement.specifiers ?? []) {
|
|
144
|
+
if (specifier.type !== "ImportSpecifier") continue;
|
|
145
|
+
const importedNode = specifier.imported;
|
|
146
|
+
const imported = importedNode.type === "Identifier" ? importedNode.name : importedNode.value;
|
|
147
|
+
const returns = RUNTIME_PRIMITIVES[imported];
|
|
148
|
+
if (returns) bindings.primitives.set(specifier.local.name, returns);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
walk(root, (node) => {
|
|
152
|
+
if (node.type !== "VariableDeclarator" || !node.init) return;
|
|
153
|
+
const returns = calledPrimitive(node.init, bindings);
|
|
154
|
+
if (returns) classify(node.id, returns, bindings.kinds);
|
|
155
|
+
});
|
|
156
|
+
return bindings;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/transform/intrinsics.ts
|
|
160
|
+
function walk2(root, visit) {
|
|
161
|
+
if (!root || typeof root !== "object" || typeof root.type !== "string") return;
|
|
162
|
+
visit(root);
|
|
163
|
+
for (const key of Object.keys(root)) {
|
|
164
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
|
|
165
|
+
const value = root[key];
|
|
166
|
+
if (Array.isArray(value)) for (const item of value) walk2(item, visit);
|
|
167
|
+
else if (value && typeof value === "object") walk2(value, visit);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function collectIntrinsicEdits(program) {
|
|
171
|
+
const edits = [];
|
|
172
|
+
const diagnostics = [];
|
|
173
|
+
const imports = /* @__PURE__ */ new Map();
|
|
174
|
+
const reported = /* @__PURE__ */ new Set();
|
|
175
|
+
const { shadowed } = resolveReactiveBindings(program);
|
|
176
|
+
walk2(program, (node) => {
|
|
177
|
+
if (node.type !== "CallExpression") return;
|
|
178
|
+
const callee = node.callee;
|
|
179
|
+
if (callee?.type !== "Identifier") return;
|
|
180
|
+
const name = callee.name;
|
|
181
|
+
if (!isIntrinsicName(name)) return;
|
|
182
|
+
if (shadowed.has(name)) {
|
|
183
|
+
if (!reported.has(name)) {
|
|
184
|
+
reported.add(name);
|
|
185
|
+
diagnostics.push({
|
|
186
|
+
name,
|
|
187
|
+
message: `${name} is reserved for the compiler, and this module binds it. The call keeps your binding's meaning; rename it to use the intrinsic.`,
|
|
188
|
+
start: callee.start
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const intrinsic = INTRINSICS[name];
|
|
194
|
+
edits.push({ start: callee.start, end: callee.end, code: intrinsic.export });
|
|
195
|
+
const forModule = imports.get(intrinsic.module) ?? /* @__PURE__ */ new Set();
|
|
196
|
+
forModule.add(intrinsic.export);
|
|
197
|
+
imports.set(intrinsic.module, forModule);
|
|
198
|
+
});
|
|
199
|
+
return { edits, diagnostics, imports };
|
|
200
|
+
}
|
|
201
|
+
function avoidBindingClashes(program, result, bound) {
|
|
202
|
+
const importedAsIs = /* @__PURE__ */ new Set();
|
|
203
|
+
for (const stmt of program.body ?? []) {
|
|
204
|
+
if (stmt.type !== "ImportDeclaration") continue;
|
|
205
|
+
const module = stmt.source.value;
|
|
206
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
207
|
+
if (spec.type !== "ImportSpecifier") continue;
|
|
208
|
+
const imported = spec.imported.name ?? spec.imported.value;
|
|
209
|
+
if (imported === spec.local.name && result.imports.get(module)?.has(imported)) {
|
|
210
|
+
importedAsIs.add(imported);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
215
|
+
for (const names of result.imports.values()) {
|
|
216
|
+
for (const name of names) if (bound.has(name) && !importedAsIs.has(name)) aliases.set(name, `__fx_${name}`);
|
|
217
|
+
}
|
|
218
|
+
if (!aliases.size) return;
|
|
219
|
+
for (const edit of result.edits) {
|
|
220
|
+
const alias = aliases.get(edit.code);
|
|
221
|
+
if (alias) edit.code = alias;
|
|
222
|
+
}
|
|
223
|
+
result.aliases = aliases;
|
|
224
|
+
}
|
|
225
|
+
function intrinsicImports(result, bound) {
|
|
226
|
+
const lines = [];
|
|
227
|
+
for (const [module, names] of [...result.imports].sort(([a], [b]) => a.localeCompare(b))) {
|
|
228
|
+
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);
|
|
229
|
+
if (wanted.length) lines.push(`import { ${wanted.join(", ")} } from ${JSON.stringify(module)};`);
|
|
230
|
+
}
|
|
231
|
+
return lines.length ? `${lines.join("\n")}
|
|
232
|
+
` : "";
|
|
233
|
+
}
|
|
234
|
+
export {
|
|
235
|
+
avoidBindingClashes,
|
|
236
|
+
collectIntrinsicEdits,
|
|
237
|
+
intrinsicImports
|
|
238
|
+
};
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/transform/props.ts
|
|
31
|
+
var props_exports = {};
|
|
32
|
+
__export(props_exports, {
|
|
33
|
+
collectPropsEdits: () => collectPropsEdits,
|
|
34
|
+
transformProps: () => transformProps
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(props_exports);
|
|
37
|
+
var import_parser = require("@babel/parser");
|
|
38
|
+
var import_magic_string = __toESM(require("magic-string"), 1);
|
|
39
|
+
|
|
40
|
+
// src/analyze/props-destructure.ts
|
|
41
|
+
function patternNames(node, out) {
|
|
42
|
+
if (!node) return;
|
|
43
|
+
switch (node.type) {
|
|
44
|
+
case "Identifier":
|
|
45
|
+
out.add(node.name);
|
|
46
|
+
return;
|
|
47
|
+
case "ObjectPattern":
|
|
48
|
+
for (const p of node.properties) {
|
|
49
|
+
if (p.type === "RestElement") patternNames(p.argument, out);
|
|
50
|
+
else patternNames(p.value, out);
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
case "ArrayPattern":
|
|
54
|
+
for (const e of node.elements) patternNames(e, out);
|
|
55
|
+
return;
|
|
56
|
+
case "AssignmentPattern":
|
|
57
|
+
patternNames(node.left, out);
|
|
58
|
+
return;
|
|
59
|
+
case "RestElement":
|
|
60
|
+
patternNames(node.argument, out);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function isSafeDefault(node) {
|
|
65
|
+
switch (node.type) {
|
|
66
|
+
case "StringLiteral":
|
|
67
|
+
case "NumericLiteral":
|
|
68
|
+
case "BooleanLiteral":
|
|
69
|
+
case "NullLiteral":
|
|
70
|
+
case "BigIntLiteral":
|
|
71
|
+
case "RegExpLiteral":
|
|
72
|
+
case "Identifier":
|
|
73
|
+
return true;
|
|
74
|
+
// ESTree spells every literal as `Literal`; both shapes reach this analysis.
|
|
75
|
+
case "Literal":
|
|
76
|
+
return true;
|
|
77
|
+
case "TemplateLiteral":
|
|
78
|
+
return node.expressions.every(isSafeDefault);
|
|
79
|
+
case "UnaryExpression":
|
|
80
|
+
return isSafeDefault(node.argument);
|
|
81
|
+
case "MemberExpression":
|
|
82
|
+
return false;
|
|
83
|
+
default:
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function walk(root, visit) {
|
|
88
|
+
if (!root || typeof root !== "object") return;
|
|
89
|
+
visit(root);
|
|
90
|
+
for (const key of Object.keys(root)) {
|
|
91
|
+
if (key === "loc" || key === "range" || key === "leadingComments" || key === "trailingComments") continue;
|
|
92
|
+
const value = root[key];
|
|
93
|
+
if (Array.isArray(value)) {
|
|
94
|
+
for (const item of value) if (item && typeof item === "object") walk(item, visit);
|
|
95
|
+
} else if (value && typeof value === "object" && typeof value.type === "string") {
|
|
96
|
+
walk(value, visit);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function reassignedNames(body) {
|
|
101
|
+
const written = /* @__PURE__ */ new Set();
|
|
102
|
+
walk(body, (node) => {
|
|
103
|
+
if (node.type === "AssignmentExpression") patternNames(node.left, written);
|
|
104
|
+
else if (node.type === "UpdateExpression") {
|
|
105
|
+
const arg = node.argument;
|
|
106
|
+
if (arg?.type === "Identifier") written.add(arg.name);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return written;
|
|
110
|
+
}
|
|
111
|
+
function shadowedNames(body, candidates) {
|
|
112
|
+
const shadowed = /* @__PURE__ */ new Set();
|
|
113
|
+
const note = (node) => {
|
|
114
|
+
const names = /* @__PURE__ */ new Set();
|
|
115
|
+
patternNames(node, names);
|
|
116
|
+
for (const n of names) if (candidates.has(n)) shadowed.add(n);
|
|
117
|
+
};
|
|
118
|
+
walk(body, (node) => {
|
|
119
|
+
switch (node.type) {
|
|
120
|
+
case "VariableDeclarator":
|
|
121
|
+
note(node.id);
|
|
122
|
+
return;
|
|
123
|
+
case "FunctionDeclaration":
|
|
124
|
+
case "FunctionExpression":
|
|
125
|
+
case "ArrowFunctionExpression":
|
|
126
|
+
note(node.id);
|
|
127
|
+
for (const p of node.params ?? []) note(p);
|
|
128
|
+
return;
|
|
129
|
+
case "CatchClause":
|
|
130
|
+
note(node.param);
|
|
131
|
+
return;
|
|
132
|
+
case "ClassDeclaration":
|
|
133
|
+
case "ClassExpression":
|
|
134
|
+
note(node.id);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return shadowed;
|
|
139
|
+
}
|
|
140
|
+
function collect(pattern, path, plan) {
|
|
141
|
+
for (const property of pattern.properties ?? []) {
|
|
142
|
+
if (property.type === "RestElement") {
|
|
143
|
+
const argument = property.argument;
|
|
144
|
+
if (argument?.type !== "Identifier" || path.length > 0) {
|
|
145
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
146
|
+
patternNames(argument, names2);
|
|
147
|
+
for (const name of names2) plan.bails.push({ name, reason: "rest" });
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
plan.rest = { name: argument.name, keys: [] };
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (property.computed) {
|
|
154
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
155
|
+
patternNames(property.value, names2);
|
|
156
|
+
for (const name of names2) plan.bails.push({ name, reason: "computed" });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const key = property.key;
|
|
160
|
+
const propertyName = key.type === "Identifier" ? key.name : key.value;
|
|
161
|
+
let value = property.value;
|
|
162
|
+
let fallback;
|
|
163
|
+
if (value.type === "AssignmentPattern") {
|
|
164
|
+
fallback = value.right;
|
|
165
|
+
value = value.left;
|
|
166
|
+
}
|
|
167
|
+
const here = [...path, propertyName];
|
|
168
|
+
if (value.type === "Identifier") {
|
|
169
|
+
if (fallback && !isSafeDefault(fallback)) {
|
|
170
|
+
plan.bails.push({ name: value.name, reason: "unsafe-default" });
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
plan.reads.push({ name: value.name, path: here, ...fallback ? { fallback } : {} });
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (value.type === "ObjectPattern") {
|
|
177
|
+
if (fallback) {
|
|
178
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
179
|
+
patternNames(value, names2);
|
|
180
|
+
for (const name of names2) plan.bails.push({ name, reason: "unsafe-default" });
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
collect(value, here, plan);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const names = /* @__PURE__ */ new Set();
|
|
187
|
+
patternNames(value, names);
|
|
188
|
+
for (const name of names) plan.bails.push({ name, reason: "computed" });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function planPropsDestructure(pattern, body) {
|
|
192
|
+
const plan = { reads: [], bails: [] };
|
|
193
|
+
if (pattern?.type !== "ObjectPattern") return plan;
|
|
194
|
+
collect(pattern, [], plan);
|
|
195
|
+
if (plan.rest) {
|
|
196
|
+
if (body?.type !== "BlockStatement") {
|
|
197
|
+
plan.bails.push({ name: plan.rest.name, reason: "rest" });
|
|
198
|
+
delete plan.rest;
|
|
199
|
+
} else {
|
|
200
|
+
plan.rest.keys = (pattern.properties ?? []).filter((p) => p.type !== "RestElement" && !p.computed).map((p) => {
|
|
201
|
+
const key = p.key;
|
|
202
|
+
return key.type === "Identifier" ? key.name : key.value;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (plan.reads.length === 0 && !plan.rest) return plan;
|
|
207
|
+
const candidates = new Set(plan.reads.map((r) => r.name));
|
|
208
|
+
if (plan.rest) candidates.add(plan.rest.name);
|
|
209
|
+
const written = reassignedNames(body);
|
|
210
|
+
const shadowed = shadowedNames(body, candidates);
|
|
211
|
+
const kept = [];
|
|
212
|
+
for (const read of plan.reads) {
|
|
213
|
+
if (written.has(read.name)) plan.bails.push({ name: read.name, reason: "reassigned" });
|
|
214
|
+
else if (shadowed.has(read.name)) plan.bails.push({ name: read.name, reason: "shadowed" });
|
|
215
|
+
else kept.push(read);
|
|
216
|
+
}
|
|
217
|
+
plan.reads = kept;
|
|
218
|
+
if (plan.rest && written.has(plan.rest.name)) {
|
|
219
|
+
plan.bails.push({ name: plan.rest.name, reason: "reassigned" });
|
|
220
|
+
delete plan.rest;
|
|
221
|
+
} else if (plan.rest && shadowed.has(plan.rest.name)) {
|
|
222
|
+
plan.bails.push({ name: plan.rest.name, reason: "shadowed" });
|
|
223
|
+
delete plan.rest;
|
|
224
|
+
}
|
|
225
|
+
return plan;
|
|
226
|
+
}
|
|
227
|
+
function explainBail(reason) {
|
|
228
|
+
switch (reason) {
|
|
229
|
+
case "rest":
|
|
230
|
+
return "this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters";
|
|
231
|
+
case "computed":
|
|
232
|
+
return "the property is not known until it runs";
|
|
233
|
+
case "reassigned":
|
|
234
|
+
return "the binding is assigned to, and props are read-only";
|
|
235
|
+
case "shadowed":
|
|
236
|
+
return "an inner scope binds the same name";
|
|
237
|
+
case "unsafe-default":
|
|
238
|
+
return "the default would have to run again on every read";
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/transform/bindings.ts
|
|
243
|
+
function patternNames2(node, out) {
|
|
244
|
+
if (!node) return;
|
|
245
|
+
switch (node.type) {
|
|
246
|
+
case "Identifier":
|
|
247
|
+
out.add(node.name);
|
|
248
|
+
return;
|
|
249
|
+
case "ObjectPattern":
|
|
250
|
+
for (const p of node.properties) {
|
|
251
|
+
if (p.type === "RestElement") patternNames2(p.argument, out);
|
|
252
|
+
else patternNames2(p.value, out);
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
case "ArrayPattern":
|
|
256
|
+
for (const e of node.elements) patternNames2(e, out);
|
|
257
|
+
return;
|
|
258
|
+
case "AssignmentPattern":
|
|
259
|
+
patternNames2(node.left, out);
|
|
260
|
+
return;
|
|
261
|
+
case "RestElement":
|
|
262
|
+
patternNames2(node.argument, out);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function declared(node, out) {
|
|
267
|
+
switch (node.type) {
|
|
268
|
+
case "ImportDeclaration":
|
|
269
|
+
for (const s of node.specifiers) patternNames2(s.local, out);
|
|
270
|
+
return;
|
|
271
|
+
case "VariableDeclaration":
|
|
272
|
+
for (const d of node.declarations) patternNames2(d.id, out);
|
|
273
|
+
return;
|
|
274
|
+
case "FunctionDeclaration":
|
|
275
|
+
case "ClassDeclaration":
|
|
276
|
+
patternNames2(node.id, out);
|
|
277
|
+
return;
|
|
278
|
+
case "ExportNamedDeclaration":
|
|
279
|
+
case "ExportDefaultDeclaration":
|
|
280
|
+
if (node.declaration) declared(node.declaration, out);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function moduleBindings(program) {
|
|
285
|
+
const names = /* @__PURE__ */ new Set();
|
|
286
|
+
for (const statement of program.body) declared(statement, names);
|
|
287
|
+
return names;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/transform/props.ts
|
|
291
|
+
function walk2(root, visit, parent = null) {
|
|
292
|
+
if (!root || typeof root !== "object" || typeof root.type !== "string") return;
|
|
293
|
+
if (root.type.startsWith("TS")) return;
|
|
294
|
+
if (visit(root, parent) === false) return;
|
|
295
|
+
for (const key of Object.keys(root)) {
|
|
296
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
|
|
297
|
+
const value = root[key];
|
|
298
|
+
if (Array.isArray(value)) {
|
|
299
|
+
for (const item of value) walk2(item, visit, root);
|
|
300
|
+
} else if (value && typeof value === "object") {
|
|
301
|
+
walk2(value, visit, root);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function isComponentName(name) {
|
|
306
|
+
return !!name && name[0] >= "A" && name[0] <= "Z";
|
|
307
|
+
}
|
|
308
|
+
function componentFunctions(program) {
|
|
309
|
+
const found = [];
|
|
310
|
+
walk2(program, (node) => {
|
|
311
|
+
if (node.type === "FunctionDeclaration" && isComponentName(node.id?.name)) {
|
|
312
|
+
found.push(node);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (node.type === "VariableDeclarator" && isComponentName(node.id?.name)) {
|
|
316
|
+
const init = node.init;
|
|
317
|
+
if (init && (init.type === "ArrowFunctionExpression" || init.type === "FunctionExpression")) found.push(init);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
return found;
|
|
321
|
+
}
|
|
322
|
+
function usedNames(fn) {
|
|
323
|
+
const names = /* @__PURE__ */ new Set();
|
|
324
|
+
walk2(fn, (node) => {
|
|
325
|
+
if (node.type === "Identifier") names.add(node.name);
|
|
326
|
+
});
|
|
327
|
+
return names;
|
|
328
|
+
}
|
|
329
|
+
function isReferencePosition(node, parent) {
|
|
330
|
+
if (!parent) return true;
|
|
331
|
+
switch (parent.type) {
|
|
332
|
+
case "MemberExpression":
|
|
333
|
+
case "OptionalMemberExpression":
|
|
334
|
+
return !(parent.property === node && !parent.computed);
|
|
335
|
+
case "ObjectProperty":
|
|
336
|
+
case "ObjectMethod":
|
|
337
|
+
case "ClassProperty":
|
|
338
|
+
case "ClassMethod":
|
|
339
|
+
return !(parent.key === node && !parent.computed);
|
|
340
|
+
case "LabeledStatement":
|
|
341
|
+
case "BreakStatement":
|
|
342
|
+
case "ContinueStatement":
|
|
343
|
+
return parent.label !== node;
|
|
344
|
+
case "ImportSpecifier":
|
|
345
|
+
case "ExportSpecifier":
|
|
346
|
+
return false;
|
|
347
|
+
default:
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function collectPropsEdits(program, code, options = {}) {
|
|
352
|
+
const edits = [];
|
|
353
|
+
const diagnostics = [];
|
|
354
|
+
const used = /* @__PURE__ */ new Set();
|
|
355
|
+
for (const fn of componentFunctions(program)) {
|
|
356
|
+
const pattern = fn.params?.[0];
|
|
357
|
+
if (pattern?.type !== "ObjectPattern") continue;
|
|
358
|
+
const plan = planPropsDestructure(pattern, fn.body);
|
|
359
|
+
for (const b of plan.bails) {
|
|
360
|
+
diagnostics.push({ name: b.name, reason: b.reason, message: explainBail(b.reason), start: pattern.start });
|
|
361
|
+
}
|
|
362
|
+
if (plan.bails.length > 0) continue;
|
|
363
|
+
if (plan.reads.length === 0 && !plan.rest) continue;
|
|
364
|
+
const taken = usedNames(fn);
|
|
365
|
+
let parameter = options.parameterName ?? "props";
|
|
366
|
+
while (taken.has(parameter)) parameter = `_${parameter}`;
|
|
367
|
+
const replacement = /* @__PURE__ */ new Map();
|
|
368
|
+
for (const read of plan.reads) {
|
|
369
|
+
const access = `${parameter}.${read.path.join(".")}`;
|
|
370
|
+
const fallback = read.fallback;
|
|
371
|
+
replacement.set(
|
|
372
|
+
read.name,
|
|
373
|
+
fallback ? `(${access} === undefined ? ${code.slice(fallback.start, fallback.end)} : ${access})` : access
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
const annotation = pattern.typeAnnotation;
|
|
377
|
+
edits.push({ start: pattern.start, end: annotation?.start ?? pattern.end, code: parameter });
|
|
378
|
+
if (plan.rest) {
|
|
379
|
+
const keys = plan.rest.keys.map((k) => JSON.stringify(k)).join(", ");
|
|
380
|
+
const body = fn.body;
|
|
381
|
+
edits.push({
|
|
382
|
+
start: body.start + 1,
|
|
383
|
+
end: body.start + 1,
|
|
384
|
+
code: `
|
|
385
|
+
const [, ${plan.rest.name}] = splitProps(${parameter}, [${keys}]);`
|
|
386
|
+
});
|
|
387
|
+
used.add("splitProps");
|
|
388
|
+
}
|
|
389
|
+
const matches = [];
|
|
390
|
+
walk2(fn.body, (node, parent) => {
|
|
391
|
+
if (node.type !== "Identifier") return void 0;
|
|
392
|
+
const text = replacement.get(node.name);
|
|
393
|
+
if (!text) return void 0;
|
|
394
|
+
const shorthand = parent?.type === "ObjectProperty" && parent.shorthand && parent.value === node;
|
|
395
|
+
if (!shorthand && !isReferencePosition(node, parent)) return void 0;
|
|
396
|
+
const path = plan.reads.find((r) => r.name === node.name).path;
|
|
397
|
+
matches.push({ node, parent: shorthand ? parent : null, text, property: path[path.length - 1] });
|
|
398
|
+
return void 0;
|
|
399
|
+
});
|
|
400
|
+
for (const match of matches) {
|
|
401
|
+
if (match.parent) {
|
|
402
|
+
edits.push({ start: match.parent.start, end: match.parent.end, code: `${match.node.name}: ${match.text}` });
|
|
403
|
+
} else {
|
|
404
|
+
edits.push({ start: match.node.start, end: match.node.end, code: match.text });
|
|
405
|
+
}
|
|
406
|
+
asMemberRead(match.node, parameter, match.property);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return { edits, diagnostics, used };
|
|
410
|
+
}
|
|
411
|
+
function asMemberRead(node, parameter, property) {
|
|
412
|
+
node.type = "MemberExpression";
|
|
413
|
+
node.computed = false;
|
|
414
|
+
node.optional = false;
|
|
415
|
+
node.object = { type: "Identifier", name: parameter, start: node.start, end: node.start };
|
|
416
|
+
node.property = { type: "Identifier", name: property, start: node.end, end: node.end };
|
|
417
|
+
delete node["name"];
|
|
418
|
+
}
|
|
419
|
+
function transformProps(code, filename = "module.tsx", options = {}) {
|
|
420
|
+
const ast = (0, import_parser.parse)(code, {
|
|
421
|
+
sourceType: "module",
|
|
422
|
+
plugins: ["typescript", "jsx"],
|
|
423
|
+
errorRecovery: true
|
|
424
|
+
});
|
|
425
|
+
const { edits, diagnostics, used } = collectPropsEdits(ast.program, code, options);
|
|
426
|
+
const source = new import_magic_string.default(code);
|
|
427
|
+
for (const e of edits) {
|
|
428
|
+
if (e.start === e.end) source.appendLeft(e.start, e.code);
|
|
429
|
+
else source.overwrite(e.start, e.end, e.code);
|
|
430
|
+
}
|
|
431
|
+
if (used.has("splitProps") && !moduleBindings(ast.program).has("splitProps")) {
|
|
432
|
+
source.prepend(`import { splitProps } from ${JSON.stringify(options.runtimeModule ?? "@fluixi/dom")};
|
|
433
|
+
`);
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
code: source.toString(),
|
|
437
|
+
map: source.generateMap({ source: filename, includeContent: true, hires: true }),
|
|
438
|
+
diagnostics,
|
|
439
|
+
rewritten: edits.filter((e) => e.code !== (options.parameterName ?? "props")).length
|
|
440
|
+
};
|
|
441
|
+
}
|