@fluixi/compiler 1.0.0-alpha.75 → 1.0.0-alpha.77

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.
Files changed (73) hide show
  1. package/README.md +38 -2
  2. package/dist/analyze/intrinsics.cjs +1 -0
  3. package/dist/analyze/intrinsics.d.ts +67 -0
  4. package/dist/analyze/intrinsics.d.ts.map +1 -0
  5. package/dist/analyze/intrinsics.js +91 -0
  6. package/dist/analyze/intrinsics.mjs +1 -0
  7. package/dist/analyze/props-destructure.cjs +1 -0
  8. package/dist/analyze/props-destructure.d.ts +84 -0
  9. package/dist/analyze/props-destructure.d.ts.map +1 -0
  10. package/dist/analyze/props-destructure.js +272 -0
  11. package/dist/analyze/props-destructure.mjs +1 -0
  12. package/dist/analyze/reactive-bindings.cjs +1 -0
  13. package/dist/analyze/reactive-bindings.d.ts +43 -0
  14. package/dist/analyze/reactive-bindings.d.ts.map +1 -0
  15. package/dist/analyze/reactive-bindings.js +191 -0
  16. package/dist/analyze/reactive-bindings.mjs +1 -0
  17. package/dist/{babel-GXO3KAVI.mjs → babel-YQ42WUS3.mjs} +1 -1
  18. package/dist/chunk-545LMC5W.mjs +1 -0
  19. package/dist/{chunk-TIE4XNAM.mjs → chunk-L2QPV25P.mjs} +1 -1
  20. package/dist/frontend/babel/build-ir-lit.cjs +1 -1
  21. package/dist/frontend/babel/build-ir-lit.mjs +1 -1
  22. package/dist/frontend/babel/build-ir.cjs +1 -1
  23. package/dist/frontend/babel/build-ir.mjs +1 -1
  24. package/dist/frontend/babel/index.cjs +1 -1
  25. package/dist/frontend/babel/index.mjs +1 -1
  26. package/dist/frontend/babel/lower-template.cjs +1 -1
  27. package/dist/frontend/babel/lower-template.mjs +1 -1
  28. package/dist/frontend/babel/plugin.cjs +1 -1
  29. package/dist/frontend/babel/plugin.mjs +1 -1
  30. package/dist/index.cjs +8 -8
  31. package/dist/index.mjs +9 -9
  32. package/dist/integrations.cjs +19 -14
  33. package/dist/integrations.d.ts +13 -0
  34. package/dist/integrations.d.ts.map +1 -1
  35. package/dist/integrations.js +52 -2
  36. package/dist/integrations.mjs +11 -11
  37. package/dist/lower/compile-template.cjs +1 -1
  38. package/dist/lower/compile-template.mjs +1 -1
  39. package/dist/lower/template.cjs +1 -1
  40. package/dist/lower/template.d.ts.map +1 -1
  41. package/dist/lower/template.js +7 -5
  42. package/dist/lower/template.mjs +1 -1
  43. package/dist/resolve/component-globals.cjs +9 -9
  44. package/dist/resolve/component-globals.d.ts +8 -0
  45. package/dist/resolve/component-globals.d.ts.map +1 -1
  46. package/dist/resolve/component-globals.js +17 -3
  47. package/dist/resolve/component-globals.mjs +9 -9
  48. package/dist/resolve/write-globals.cjs +9 -9
  49. package/dist/resolve/write-globals.mjs +9 -9
  50. package/dist/transform/index.cjs +6 -1
  51. package/dist/transform/index.d.ts +4 -0
  52. package/dist/transform/index.d.ts.map +1 -1
  53. package/dist/transform/index.js +2 -0
  54. package/dist/transform/index.mjs +15 -10
  55. package/dist/transform/intrinsics.cjs +3 -0
  56. package/dist/transform/intrinsics.d.ts +22 -0
  57. package/dist/transform/intrinsics.d.ts.map +1 -0
  58. package/dist/transform/intrinsics.js +78 -0
  59. package/dist/transform/intrinsics.mjs +3 -0
  60. package/dist/transform/props.cjs +3 -0
  61. package/dist/transform/props.d.ts +46 -0
  62. package/dist/transform/props.d.ts.map +1 -0
  63. package/dist/transform/props.js +221 -0
  64. package/dist/transform/props.mjs +12 -0
  65. package/dist/transform/templates.cjs +5 -1
  66. package/dist/transform/templates.d.ts +36 -0
  67. package/dist/transform/templates.d.ts.map +1 -1
  68. package/dist/transform/templates.js +175 -7
  69. package/dist/transform/templates.mjs +14 -10
  70. package/dist/transform-ZGXUDFEZ.mjs +8 -0
  71. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  72. package/package.json +3 -3
  73. package/dist/transform-PJX2GNSV.mjs +0 -3
package/README.md CHANGED
@@ -38,6 +38,42 @@ gets an RPC stub, the server build keeps and registers the body.
38
38
  Most apps don't use this package directly — [`@fluixi/vite-plugin`](../vite-plugin) (and
39
39
  [`@fluixi/start`](../start)) wrap it.
40
40
 
41
+ ## What it does to your code
42
+
43
+ Beyond turning markup into DOM calls:
44
+
45
+ **Props you destructured stay reactive.** `function Card({ title })` compiles to
46
+ `props.title` at each use, so the binding keeps updating, and `...rest` becomes the
47
+ `splitProps` call you would have written. Anything it can't prove safe — a reassigned
48
+ binding, a computed key, a default it would have to re-run per read — is left exactly as
49
+ written and reported. On by default; set `propsDestructure: false` for a package that ships
50
+ its **source** for consumers to compile, since the rewrite belongs to whoever compiles.
51
+
52
+ **`$` intrinsics resolve without an import.** `$signal`, `$memo`, `$effect`, `$store`,
53
+ `$resource`, `$selector`, `$deferred`, `$untrack`, `$untrackStore` compile to the runtime
54
+ calls they stand for, and the import is added for what a module actually used. A primitive
55
+ is recognised by the binding it came from, never by name: `import { signal as state }` is
56
+ recognised, a local `function signal()` is not. A module that binds a `$` name keeps its
57
+ own meaning and gets a diagnostic.
58
+
59
+ **Unimported tags resolve through rules.** `resolve` says where a capitalised tag comes
60
+ from — an entry per component, or one pattern for a family:
61
+
62
+ ```ts
63
+ createVitePlugin({ resolve: [{ match: /^([A-Z]\w+)$/, module: '/src/components/$1.tsx' }] })
64
+ ```
65
+
66
+ **`load:` splits a component into its own chunk.** `load:visible`, `load:idle`,
67
+ `load:interaction`, `load:media` decide when its module is fetched. It works on a component
68
+ a rule supplies and on one you imported yourself — in the second case the static import is
69
+ removed, which only happens when the name is used nowhere but as a tag.
70
+
71
+ **It says when it couldn't do these things.** A tag nothing supplies and a `load:` that
72
+ can't apply both build cleanly and fail at runtime, so they're reported at build time with
73
+ the reason. The bundler adapters print them; `TransformResult` carries them as
74
+ `propsDiagnostics`, `intrinsicDiagnostics`, `loadDiagnostics` and `unresolvedDiagnostics`
75
+ if you're driving the transform yourself.
76
+
41
77
  ## 📦 Installation
42
78
 
43
79
  ```sh
@@ -68,8 +104,8 @@ import { transformTemplates } from '@fluixi/compiler/transform';
68
104
  const { code, map } = transformTemplates(source, 'App.tsx', {})!;
69
105
  ```
70
106
 
71
- `transformTemplates` returns `null` when a module has no JSX and no templates, so a
72
- bundler can leave the file untouched.
107
+ `transformTemplates` returns `null` when there is nothing to do — no JSX, no templates, no
108
+ `$` intrinsics and nothing to report — so a bundler can leave the file untouched.
73
109
 
74
110
  ### Compiling through Babel
75
111
 
@@ -0,0 +1 @@
1
+ "use strict";var c=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var d=(e,r)=>{for(var n in r)c(e,n,{get:r[n],enumerable:!0})},f=(e,r,n,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of u(r))!m.call(e,o)&&o!==n&&c(e,o,{get:()=>r[o],enumerable:!(i=l(r,o))||i.enumerable});return e};var x=e=>f(c({},"__esModule",{value:!0}),e);var h={};d(h,{INTRINSICS:()=>s,PRIMITIVE_MODULES:()=>a,REACTIVE_MODULE:()=>t,RUNTIME_PRIMITIVES:()=>p,isIntrinsicName:()=>R,isPrimitiveModule:()=>v,mayHaveIntrinsic:()=>I});module.exports=x(h);var t="@fluixi/reactive/signal",s={$signal:{export:"signal",module:t,returns:"signal-handle"},$memo:{export:"memo",module:t,returns:"memo-handle"},$effect:{export:"effect",module:t,returns:"effect"},$store:{export:"store",module:"@fluixi/reactive/store",returns:"store-handle"},$resource:{export:"resource",module:t,returns:"resource-handle"},$selector:{export:"createSelector",module:t,returns:"memo-accessor"},$deferred:{export:"createDeferred",module:t,returns:"memo-accessor"},$untrack:{export:"untrack",module:t,returns:"plain"},$untrackStore:{export:"untrackStore",module:"@fluixi/reactive/store",returns:"plain"}},p={signal:"signal-handle",memo:"memo-handle",effect:"effect",store:"store-handle",createSignal:["signal-accessor","signal-setter"],createMemo:"memo-accessor",createEffect:"effect",createRenderEffect:"effect",createStore:"reactive-object",resource:"resource-handle",createResource:"reactive-object",createSelector:"memo-accessor",createDeferred:"memo-accessor"},a=["@fluixi/reactive","@fluixi/reactive/signal","@fluixi/reactive/signal-next","@fluixi/reactive/store","@fluixi/core","@fluixi/core/rx"],g=new RegExp(`\\$(?:${Object.keys(s).map(e=>e.slice(1)).join("|")})\\s*\\(`);function I(e){return g.test(e)}function R(e){return Object.prototype.hasOwnProperty.call(s,e)}function v(e){return a.includes(e)}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The reactive primitives the compiler knows by name, in one place.
3
+ *
4
+ * Two ways to write the same thing. The runtime call, which needs an import and works
5
+ * without us:
6
+ *
7
+ * import { createSignal } from '@fluixi/reactive/signal';
8
+ * const count = createSignal(0);
9
+ *
10
+ * And the intrinsic, which the compiler resolves and imports for you:
11
+ *
12
+ * const count = $signal(0);
13
+ *
14
+ * They are not two reactive systems. `$signal` compiles to the same `createSignal` call,
15
+ * so there's one graph, one lifecycle, one SSR story. The `$` form is authoring sugar
16
+ * the compiler understands; the runtime form stays public, because a library that never
17
+ * runs this compiler still has to be able to write reactive code.
18
+ *
19
+ * Everything the compiler needs to know about a primitive lives in this table rather
20
+ * than spread across passes, so adding one is an entry, not a new code path.
21
+ */
22
+ /** What a binding holds, once we know where it came from. */
23
+ export type ReactiveKind = 'plain'
24
+ /** `signal(0)` — one object, read with `.get()` and written with `.set()`. */
25
+ | 'signal-handle'
26
+ /** `memo(fn)` — read-only, so `.get()` only. */
27
+ | 'memo-handle'
28
+ /** `store(obj)` — read properties directly, `.set()` writes. */
29
+ | 'store-handle'
30
+ /** `resource(fn)` — `.get()` reads, with `.loading`/`.latest`/`.refetch()` on it. */
31
+ | 'resource-handle'
32
+ /** The accessor half of the tuple form, `const [count] = createSignal(0)`. */
33
+ | 'signal-accessor' | 'signal-setter' | 'memo-accessor' | 'effect' | 'reactive-object';
34
+ export interface Intrinsic {
35
+ /** Runtime export this compiles to. */
36
+ export: string;
37
+ /** Module it comes from. */
38
+ module: string;
39
+ /**
40
+ * What the call yields. A tuple means the call is destructured into that many
41
+ * bindings — `createSignal` gives an accessor and a setter, in that order.
42
+ */
43
+ returns: ReactiveKind | readonly ReactiveKind[];
44
+ }
45
+ /** Module the reactive primitives are imported from when the compiler adds the import. */
46
+ export declare const REACTIVE_MODULE = "@fluixi/reactive/signal";
47
+ /**
48
+ * `$name` → the runtime it stands for.
49
+ *
50
+ * The `$` prefix is reserved. A local binding of the same name wins — it has to, or the
51
+ * compiler would rewrite code that means something else — and that's reported rather
52
+ * than done quietly.
53
+ */
54
+ export declare const INTRINSICS: Readonly<Record<string, Intrinsic>>;
55
+ /**
56
+ * The runtime names, for the other direction: source that imports `createSignal` gets
57
+ * classified the same way as source that writes `$signal`, so later passes see one
58
+ * vocabulary whichever form the author used.
59
+ */
60
+ export declare const RUNTIME_PRIMITIVES: Readonly<Record<string, Intrinsic['returns']>>;
61
+ /** Modules whose exports count as reactive primitives. */
62
+ export declare const PRIMITIVE_MODULES: readonly string[];
63
+ export declare function mayHaveIntrinsic(code: string): boolean;
64
+ export declare function isIntrinsicName(name: string): boolean;
65
+ /** Whether a module path exports the reactive primitives. */
66
+ export declare function isPrimitiveModule(source: string): boolean;
67
+ //# sourceMappingURL=intrinsics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intrinsics.d.ts","sourceRoot":"","sources":["../../src/analyze/intrinsics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GACpB,OAAO;AACT,8EAA8E;GAC5E,eAAe;AACjB,gDAAgD;GAC9C,aAAa;AACf,gEAAgE;GAC9D,cAAc;AAChB,qFAAqF;GACnF,iBAAiB;AACnB,8EAA8E;GAC5E,iBAAiB,GACjB,eAAe,GACf,eAAe,GACf,QAAQ,GACR,iBAAiB,CAAC;AAEtB,MAAM,WAAW,SAAS;IACxB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,YAAY,GAAG,SAAS,YAAY,EAAE,CAAC;CACjD;AAED,0FAA0F;AAC1F,eAAO,MAAM,eAAe,4BAA4B,CAAC;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAmB1D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAc7E,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAO9C,CAAC;AAQF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * The reactive primitives the compiler knows by name, in one place.
3
+ *
4
+ * Two ways to write the same thing. The runtime call, which needs an import and works
5
+ * without us:
6
+ *
7
+ * import { createSignal } from '@fluixi/reactive/signal';
8
+ * const count = createSignal(0);
9
+ *
10
+ * And the intrinsic, which the compiler resolves and imports for you:
11
+ *
12
+ * const count = $signal(0);
13
+ *
14
+ * They are not two reactive systems. `$signal` compiles to the same `createSignal` call,
15
+ * so there's one graph, one lifecycle, one SSR story. The `$` form is authoring sugar
16
+ * the compiler understands; the runtime form stays public, because a library that never
17
+ * runs this compiler still has to be able to write reactive code.
18
+ *
19
+ * Everything the compiler needs to know about a primitive lives in this table rather
20
+ * than spread across passes, so adding one is an entry, not a new code path.
21
+ */
22
+ /** Module the reactive primitives are imported from when the compiler adds the import. */
23
+ export const REACTIVE_MODULE = '@fluixi/reactive/signal';
24
+ /**
25
+ * `$name` → the runtime it stands for.
26
+ *
27
+ * The `$` prefix is reserved. A local binding of the same name wins — it has to, or the
28
+ * compiler would rewrite code that means something else — and that's reported rather
29
+ * than done quietly.
30
+ */
31
+ export const INTRINSICS = {
32
+ $signal: { export: 'signal', module: REACTIVE_MODULE, returns: 'signal-handle' },
33
+ $memo: { export: 'memo', module: REACTIVE_MODULE, returns: 'memo-handle' },
34
+ $effect: { export: 'effect', module: REACTIVE_MODULE, returns: 'effect' },
35
+ $store: { export: 'store', module: '@fluixi/reactive/store', returns: 'store-handle' },
36
+ $resource: { export: 'resource', module: REACTIVE_MODULE, returns: 'resource-handle' },
37
+ // No short runtime form for these yet, so the intrinsic stands for the `create*`
38
+ // name. Still worth having — no import to write — and when a shorter form is
39
+ // designed, the change is this line rather than a compiler pass.
40
+ $selector: { export: 'createSelector', module: REACTIVE_MODULE, returns: 'memo-accessor' },
41
+ $deferred: { export: 'createDeferred', module: REACTIVE_MODULE, returns: 'memo-accessor' },
42
+ // Not value constructors, but the compiler has to know them: they change what a read
43
+ // does. `untrack` suppresses dependency collection, which is exactly the kind of thing
44
+ // dependency analysis must not guess at.
45
+ $untrack: { export: 'untrack', module: REACTIVE_MODULE, returns: 'plain' },
46
+ $untrackStore: { export: 'untrackStore', module: '@fluixi/reactive/store', returns: 'plain' },
47
+ };
48
+ /**
49
+ * The runtime names, for the other direction: source that imports `createSignal` gets
50
+ * classified the same way as source that writes `$signal`, so later passes see one
51
+ * vocabulary whichever form the author used.
52
+ */
53
+ export const RUNTIME_PRIMITIVES = {
54
+ signal: 'signal-handle',
55
+ memo: 'memo-handle',
56
+ effect: 'effect',
57
+ store: 'store-handle',
58
+ createSignal: ['signal-accessor', 'signal-setter'],
59
+ createMemo: 'memo-accessor',
60
+ createEffect: 'effect',
61
+ createRenderEffect: 'effect',
62
+ createStore: 'reactive-object',
63
+ resource: 'resource-handle',
64
+ createResource: 'reactive-object',
65
+ createSelector: 'memo-accessor',
66
+ createDeferred: 'memo-accessor',
67
+ };
68
+ /** Modules whose exports count as reactive primitives. */
69
+ export const PRIMITIVE_MODULES = [
70
+ '@fluixi/reactive',
71
+ '@fluixi/reactive/signal',
72
+ '@fluixi/reactive/signal-next',
73
+ '@fluixi/reactive/store',
74
+ '@fluixi/core',
75
+ '@fluixi/core/rx',
76
+ ];
77
+ /**
78
+ * Cheap text check for the file-skipping fast path: a module with no `$` call never
79
+ * needs parsing. Non-global, so it has no lastIndex to carry between calls.
80
+ */
81
+ const INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join('|')})\\s*\\(`);
82
+ export function mayHaveIntrinsic(code) {
83
+ return INTRINSIC_CALL.test(code);
84
+ }
85
+ export function isIntrinsicName(name) {
86
+ return Object.prototype.hasOwnProperty.call(INTRINSICS, name);
87
+ }
88
+ /** Whether a module path exports the reactive primitives. */
89
+ export function isPrimitiveModule(source) {
90
+ return PRIMITIVE_MODULES.includes(source);
91
+ }
@@ -0,0 +1 @@
1
+ var r="@fluixi/reactive/signal",t={$signal:{export:"signal",module:r,returns:"signal-handle"},$memo:{export:"memo",module:r,returns:"memo-handle"},$effect:{export:"effect",module:r,returns:"effect"},$store:{export:"store",module:"@fluixi/reactive/store",returns:"store-handle"},$resource:{export:"resource",module:r,returns:"resource-handle"},$selector:{export:"createSelector",module:r,returns:"memo-accessor"},$deferred:{export:"createDeferred",module:r,returns:"memo-accessor"},$untrack:{export:"untrack",module:r,returns:"plain"},$untrackStore:{export:"untrackStore",module:"@fluixi/reactive/store",returns:"plain"}},c={signal:"signal-handle",memo:"memo-handle",effect:"effect",store:"store-handle",createSignal:["signal-accessor","signal-setter"],createMemo:"memo-accessor",createEffect:"effect",createRenderEffect:"effect",createStore:"reactive-object",resource:"resource-handle",createResource:"reactive-object",createSelector:"memo-accessor",createDeferred:"memo-accessor"},o=["@fluixi/reactive","@fluixi/reactive/signal","@fluixi/reactive/signal-next","@fluixi/reactive/store","@fluixi/core","@fluixi/core/rx"],n=new RegExp(`\\$(?:${Object.keys(t).map(e=>e.slice(1)).join("|")})\\s*\\(`);function s(e){return n.test(e)}function i(e){return Object.prototype.hasOwnProperty.call(t,e)}function a(e){return o.includes(e)}export{t as INTRINSICS,o as PRIMITIVE_MODULES,r as REACTIVE_MODULE,c as RUNTIME_PRIMITIVES,i as isIntrinsicName,a as isPrimitiveModule,s as mayHaveIntrinsic};
@@ -0,0 +1 @@
1
+ "use strict";var p=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var k=(s,t)=>{for(var e in t)p(s,e,{get:t[e],enumerable:!0})},v=(s,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of w(t))!b.call(s,a)&&a!==e&&p(s,a,{get:()=>t[a],enumerable:!(n=h(t,a))||n.enumerable});return s};var x=s=>v(p({},"__esModule",{value:!0}),s);var R={};k(R,{explainBail:()=>E,planPropsDestructure:()=>D});module.exports=x(R);function u(s,t){if(s)switch(s.type){case"Identifier":t.add(s.name);return;case"ObjectPattern":for(let e of s.properties)e.type==="RestElement"?u(e.argument,t):u(e.value,t);return;case"ArrayPattern":for(let e of s.elements)u(e,t);return;case"AssignmentPattern":u(s.left,t);return;case"RestElement":u(s.argument,t);return}}function m(s){switch(s.type){case"StringLiteral":case"NumericLiteral":case"BooleanLiteral":case"NullLiteral":case"BigIntLiteral":case"RegExpLiteral":case"Identifier":return!0;case"Literal":return!0;case"TemplateLiteral":return s.expressions.every(m);case"UnaryExpression":return m(s.argument);case"MemberExpression":return!1;default:return!1}}function f(s,t){if(!(!s||typeof s!="object")){t(s);for(let e of Object.keys(s)){if(e==="loc"||e==="range"||e==="leadingComments"||e==="trailingComments")continue;let n=s[e];if(Array.isArray(n))for(let a of n)a&&typeof a=="object"&&f(a,t);else n&&typeof n=="object"&&typeof n.type=="string"&&f(n,t)}}}function P(s){let t=new Set;return f(s,e=>{if(e.type==="AssignmentExpression")u(e.left,t);else if(e.type==="UpdateExpression"){let n=e.argument;n?.type==="Identifier"&&t.add(n.name)}}),t}function S(s,t){let e=new Set,n=a=>{let c=new Set;u(a,c);for(let i of c)t.has(i)&&e.add(i)};return f(s,a=>{switch(a.type){case"VariableDeclarator":n(a.id);return;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":n(a.id);for(let c of a.params??[])n(c);return;case"CatchClause":n(a.param);return;case"ClassDeclaration":case"ClassExpression":n(a.id);return}}),e}function N(s,t,e){for(let n of s.properties??[]){if(n.type==="RestElement"){let o=n.argument;if(o?.type!=="Identifier"||t.length>0){let l=new Set;u(o,l);for(let y of l)e.bails.push({name:y,reason:"rest"});continue}e.rest={name:o.name,keys:[]};continue}if(n.computed){let o=new Set;u(n.value,o);for(let l of o)e.bails.push({name:l,reason:"computed"});continue}let a=n.key,c=a.type==="Identifier"?a.name:a.value,i=n.value,r;i.type==="AssignmentPattern"&&(r=i.right,i=i.left);let d=[...t,c];if(i.type==="Identifier"){if(r&&!m(r)){e.bails.push({name:i.name,reason:"unsafe-default"});continue}e.reads.push({name:i.name,path:d,...r?{fallback:r}:{}});continue}if(i.type==="ObjectPattern"){if(r){let o=new Set;u(i,o);for(let l of o)e.bails.push({name:l,reason:"unsafe-default"});continue}N(i,d,e);continue}let g=new Set;u(i,g);for(let o of g)e.bails.push({name:o,reason:"computed"})}}function D(s,t){let e={reads:[],bails:[]};if(s?.type!=="ObjectPattern"||(N(s,[],e),e.rest&&(t?.type!=="BlockStatement"?(e.bails.push({name:e.rest.name,reason:"rest"}),delete e.rest):e.rest.keys=(s.properties??[]).filter(r=>r.type!=="RestElement"&&!r.computed).map(r=>{let d=r.key;return d.type==="Identifier"?d.name:d.value})),e.reads.length===0&&!e.rest))return e;let n=new Set(e.reads.map(r=>r.name));e.rest&&n.add(e.rest.name);let a=P(t),c=S(t,n),i=[];for(let r of e.reads)a.has(r.name)?e.bails.push({name:r.name,reason:"reassigned"}):c.has(r.name)?e.bails.push({name:r.name,reason:"shadowed"}):i.push(r);return e.reads=i,e.rest&&a.has(e.rest.name)?(e.bails.push({name:e.rest.name,reason:"reassigned"}),delete e.rest):e.rest&&c.has(e.rest.name)&&(e.bails.push({name:e.rest.name,reason:"shadowed"}),delete e.rest),e}function E(s){switch(s){case"rest":return"this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters";case"computed":return"the property is not known until it runs";case"reassigned":return"the binding is assigned to, and props are read-only";case"shadowed":return"an inner scope binds the same name";case"unsafe-default":return"the default would have to run again on every read"}}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Props destructuring, without losing reactivity.
3
+ *
4
+ * Props come in as an object of getters, so `props.name` re-reads every time and that
5
+ * keeps a binding current. `const { name } = props` copies the value out once, which is
6
+ * why we call splitProps in about 84 components.
7
+ *
8
+ * The plan here rewrites `name` to `props.name` at each use rather than making it an
9
+ * accessor. `() => props.name` would change the binding's type, and then every use has
10
+ * to change with it: passed to a plain function, stored in an array, compared with
11
+ * `===`. That's a whole-program job. Substitution is one function body and a rename.
12
+ *
13
+ * It does change one thing. A read that happens later sees the current value instead of
14
+ * the value at destructure time, which is the reason to do this at all. Anything past
15
+ * that I leave as written and report, so splitProps stays correct where it's still the
16
+ * right answer.
17
+ *
18
+ * No babel in here (see no-babel-in-core.spec.ts) — nodes are read structurally, the way
19
+ * transform/bindings.ts does, so either front-end can drive it.
20
+ */
21
+ interface Node {
22
+ type: string;
23
+ [key: string]: unknown;
24
+ }
25
+ /** Why a binding was left alone. All of these change more than when the read happens. */
26
+ export type DestructureBail =
27
+ /**
28
+ * A rest we can't serve: destructured further (`...{ a }`), or in a function with no
29
+ * block to put the splitProps call in (`({ a, ...rest }) => …`).
30
+ */
31
+ 'rest'
32
+ /** `const { [key]: a } = props` — we don't know the property until it runs. */
33
+ | 'computed'
34
+ /** The binding gets assigned to, and props are read-only, so it can't become a member. */
35
+ | 'reassigned'
36
+ /** An inner scope binds the same name, so a use site could mean either one. */
37
+ | 'shadowed'
38
+ /**
39
+ * A default we can't re-run on every read: a function hands out a new identity each
40
+ * time, a call runs its side effect each time.
41
+ */
42
+ | 'unsafe-default';
43
+ export interface PropsRead {
44
+ /** The local name the pattern introduced. */
45
+ name: string;
46
+ /** Property path to read through instead — `['user', 'name']` for `{ user: { name } }`. */
47
+ path: string[];
48
+ /**
49
+ * Default from the pattern. JS only applies one for `undefined`, not for null, so
50
+ * codegen has to test `=== undefined` rather than reach for `??`, and re-run it on
51
+ * every read.
52
+ */
53
+ fallback?: Node;
54
+ }
55
+ export interface DestructurePlan {
56
+ /** Bindings we can rewrite to a property read. */
57
+ reads: PropsRead[];
58
+ /** Bindings we left alone, with the reason to report. */
59
+ bails: {
60
+ name: string;
61
+ reason: DestructureBail;
62
+ }[];
63
+ /**
64
+ * A `...rest`, and the keys it has to exclude.
65
+ *
66
+ * This is what splitProps is for: it copies the getters across rather than reading
67
+ * them, which is the reason a plain `...rest` can't be rewritten. So instead of
68
+ * refusing the pattern, we write the splitProps call the author would have written.
69
+ */
70
+ rest?: {
71
+ name: string;
72
+ keys: string[];
73
+ };
74
+ }
75
+ /**
76
+ * Plan one props pattern. `pattern` is the ObjectPattern, `body` the function body its
77
+ * bindings live in. Every binding ends up in `reads` (rewrite it) or `bails` (leave it
78
+ * and say why).
79
+ */
80
+ export declare function planPropsDestructure(pattern: Node, body: Node | null | undefined): DestructurePlan;
81
+ /** Reason text for the diagnostic. */
82
+ export declare function explainBail(reason: DestructureBail): string;
83
+ export {};
84
+ //# sourceMappingURL=props-destructure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props-destructure.d.ts","sourceRoot":"","sources":["../../src/analyze/props-destructure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,yFAAyF;AACzF,MAAM,MAAM,eAAe;AACzB;;;GAGG;AACD,MAAM;AACR,+EAA+E;GAC7E,UAAU;AACZ,0FAA0F;GACxF,YAAY;AACd,+EAA+E;GAC7E,UAAU;AACZ;;;GAGG;GACD,gBAAgB,CAAC;AAErB,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,EAAE,CAAC;IACnD;;;;;;OAMG;IACH,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACzC;AAoLD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,eAAe,CAgDlG;AAED,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAa3D"}
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Props destructuring, without losing reactivity.
3
+ *
4
+ * Props come in as an object of getters, so `props.name` re-reads every time and that
5
+ * keeps a binding current. `const { name } = props` copies the value out once, which is
6
+ * why we call splitProps in about 84 components.
7
+ *
8
+ * The plan here rewrites `name` to `props.name` at each use rather than making it an
9
+ * accessor. `() => props.name` would change the binding's type, and then every use has
10
+ * to change with it: passed to a plain function, stored in an array, compared with
11
+ * `===`. That's a whole-program job. Substitution is one function body and a rename.
12
+ *
13
+ * It does change one thing. A read that happens later sees the current value instead of
14
+ * the value at destructure time, which is the reason to do this at all. Anything past
15
+ * that I leave as written and report, so splitProps stays correct where it's still the
16
+ * right answer.
17
+ *
18
+ * No babel in here (see no-babel-in-core.spec.ts) — nodes are read structurally, the way
19
+ * transform/bindings.ts does, so either front-end can drive it.
20
+ */
21
+ /** Every name a pattern introduces, so we can check each one for shadowing and writes. */
22
+ function patternNames(node, out) {
23
+ if (!node)
24
+ return;
25
+ switch (node.type) {
26
+ case 'Identifier':
27
+ out.add(node.name);
28
+ return;
29
+ case 'ObjectPattern':
30
+ for (const p of node.properties) {
31
+ if (p.type === 'RestElement')
32
+ patternNames(p.argument, out);
33
+ else
34
+ patternNames(p.value, out);
35
+ }
36
+ return;
37
+ case 'ArrayPattern':
38
+ for (const e of node.elements)
39
+ patternNames(e, out);
40
+ return;
41
+ case 'AssignmentPattern':
42
+ patternNames(node.left, out);
43
+ return;
44
+ case 'RestElement':
45
+ patternNames(node.argument, out);
46
+ return;
47
+ }
48
+ }
49
+ /**
50
+ * Defaults get re-run on every read now, so they have to be cheap and stable. Literals
51
+ * and identifiers are. A function isn't — it hands out a new identity each read, which
52
+ * breaks anything comparing props — and neither is a call.
53
+ */
54
+ function isSafeDefault(node) {
55
+ switch (node.type) {
56
+ case 'StringLiteral':
57
+ case 'NumericLiteral':
58
+ case 'BooleanLiteral':
59
+ case 'NullLiteral':
60
+ case 'BigIntLiteral':
61
+ case 'RegExpLiteral':
62
+ case 'Identifier':
63
+ return true;
64
+ // ESTree spells every literal as `Literal`; both shapes reach this analysis.
65
+ case 'Literal':
66
+ return true;
67
+ case 'TemplateLiteral':
68
+ return node.expressions.every(isSafeDefault);
69
+ case 'UnaryExpression':
70
+ return isSafeDefault(node.argument);
71
+ case 'MemberExpression':
72
+ // Could be a getter, and we'd be running it on every read.
73
+ return false;
74
+ default:
75
+ return false;
76
+ }
77
+ }
78
+ /** Walk everything under `root`. No visitor API here, so it's hand-rolled. */
79
+ function walk(root, visit) {
80
+ if (!root || typeof root !== 'object')
81
+ return;
82
+ visit(root);
83
+ for (const key of Object.keys(root)) {
84
+ if (key === 'loc' || key === 'range' || key === 'leadingComments' || key === 'trailingComments')
85
+ continue;
86
+ const value = root[key];
87
+ if (Array.isArray(value)) {
88
+ for (const item of value)
89
+ if (item && typeof item === 'object')
90
+ walk(item, visit);
91
+ }
92
+ else if (value && typeof value === 'object' && typeof value.type === 'string') {
93
+ walk(value, visit);
94
+ }
95
+ }
96
+ }
97
+ /** Anything written to in the body — `name = x`, `name++`, `[name] = …`. */
98
+ function reassignedNames(body) {
99
+ const written = new Set();
100
+ walk(body, (node) => {
101
+ if (node.type === 'AssignmentExpression')
102
+ patternNames(node.left, written);
103
+ else if (node.type === 'UpdateExpression') {
104
+ const arg = node.argument;
105
+ if (arg?.type === 'Identifier')
106
+ written.add(arg.name);
107
+ }
108
+ });
109
+ return written;
110
+ }
111
+ /** Names an inner scope re-binds, where a use site would mean something else. */
112
+ function shadowedNames(body, candidates) {
113
+ const shadowed = new Set();
114
+ const note = (node) => {
115
+ const names = new Set();
116
+ patternNames(node, names);
117
+ for (const n of names)
118
+ if (candidates.has(n))
119
+ shadowed.add(n);
120
+ };
121
+ walk(body, (node) => {
122
+ switch (node.type) {
123
+ case 'VariableDeclarator':
124
+ note(node.id);
125
+ return;
126
+ case 'FunctionDeclaration':
127
+ case 'FunctionExpression':
128
+ case 'ArrowFunctionExpression':
129
+ note(node.id);
130
+ for (const p of node.params ?? [])
131
+ note(p);
132
+ return;
133
+ case 'CatchClause':
134
+ note(node.param);
135
+ return;
136
+ case 'ClassDeclaration':
137
+ case 'ClassExpression':
138
+ note(node.id);
139
+ return;
140
+ }
141
+ });
142
+ return shadowed;
143
+ }
144
+ /** One level of an object pattern, recursing into nested ones. */
145
+ function collect(pattern, path, plan) {
146
+ for (const property of pattern.properties ?? []) {
147
+ if (property.type === 'RestElement') {
148
+ const argument = property.argument;
149
+ // Only a plain name. `...{ a }` would need its own splitProps and its own rules.
150
+ if (argument?.type !== 'Identifier' || path.length > 0) {
151
+ const names = new Set();
152
+ patternNames(argument, names);
153
+ for (const name of names)
154
+ plan.bails.push({ name, reason: 'rest' });
155
+ continue;
156
+ }
157
+ plan.rest = { name: argument.name, keys: [] };
158
+ continue;
159
+ }
160
+ if (property.computed) {
161
+ const names = new Set();
162
+ patternNames(property.value, names);
163
+ for (const name of names)
164
+ plan.bails.push({ name, reason: 'computed' });
165
+ continue;
166
+ }
167
+ const key = property.key;
168
+ const propertyName = (key.type === 'Identifier' ? key.name : key.value);
169
+ let value = property.value;
170
+ let fallback;
171
+ if (value.type === 'AssignmentPattern') {
172
+ fallback = value.right;
173
+ value = value.left;
174
+ }
175
+ const here = [...path, propertyName];
176
+ if (value.type === 'Identifier') {
177
+ if (fallback && !isSafeDefault(fallback)) {
178
+ plan.bails.push({ name: value.name, reason: 'unsafe-default' });
179
+ continue;
180
+ }
181
+ plan.reads.push({ name: value.name, path: here, ...(fallback ? { fallback } : {}) });
182
+ continue;
183
+ }
184
+ if (value.type === 'ObjectPattern') {
185
+ // `{ user: { name } = {} }` would have to build the default object on every read.
186
+ if (fallback) {
187
+ const names = new Set();
188
+ patternNames(value, names);
189
+ for (const name of names)
190
+ plan.bails.push({ name, reason: 'unsafe-default' });
191
+ continue;
192
+ }
193
+ collect(value, here, plan);
194
+ continue;
195
+ }
196
+ // An array pattern indexes into a value we can't prove is stable, so leave it.
197
+ const names = new Set();
198
+ patternNames(value, names);
199
+ for (const name of names)
200
+ plan.bails.push({ name, reason: 'computed' });
201
+ }
202
+ }
203
+ /**
204
+ * Plan one props pattern. `pattern` is the ObjectPattern, `body` the function body its
205
+ * bindings live in. Every binding ends up in `reads` (rewrite it) or `bails` (leave it
206
+ * and say why).
207
+ */
208
+ export function planPropsDestructure(pattern, body) {
209
+ const plan = { reads: [], bails: [] };
210
+ if (pattern?.type !== 'ObjectPattern')
211
+ return plan;
212
+ collect(pattern, [], plan);
213
+ if (plan.rest) {
214
+ // The splitProps call is a statement, so there has to be somewhere to put it.
215
+ if (body?.type !== 'BlockStatement') {
216
+ plan.bails.push({ name: plan.rest.name, reason: 'rest' });
217
+ delete plan.rest;
218
+ }
219
+ else {
220
+ // Keys the rest has to exclude: every top-level property the pattern names.
221
+ plan.rest.keys = (pattern.properties ?? [])
222
+ .filter((p) => p.type !== 'RestElement' && !p.computed)
223
+ .map((p) => {
224
+ const key = p.key;
225
+ return (key.type === 'Identifier' ? key.name : key.value);
226
+ });
227
+ }
228
+ }
229
+ if (plan.reads.length === 0 && !plan.rest)
230
+ return plan;
231
+ const candidates = new Set(plan.reads.map((r) => r.name));
232
+ if (plan.rest)
233
+ candidates.add(plan.rest.name);
234
+ const written = reassignedNames(body);
235
+ const shadowed = shadowedNames(body, candidates);
236
+ const kept = [];
237
+ for (const read of plan.reads) {
238
+ if (written.has(read.name))
239
+ plan.bails.push({ name: read.name, reason: 'reassigned' });
240
+ else if (shadowed.has(read.name))
241
+ plan.bails.push({ name: read.name, reason: 'shadowed' });
242
+ else
243
+ kept.push(read);
244
+ }
245
+ plan.reads = kept;
246
+ // The rest binding is declared by the code we emit, so it has to survive the same
247
+ // checks: reassigning it or shadowing the name would break what we wrote.
248
+ if (plan.rest && written.has(plan.rest.name)) {
249
+ plan.bails.push({ name: plan.rest.name, reason: 'reassigned' });
250
+ delete plan.rest;
251
+ }
252
+ else if (plan.rest && shadowed.has(plan.rest.name)) {
253
+ plan.bails.push({ name: plan.rest.name, reason: 'shadowed' });
254
+ delete plan.rest;
255
+ }
256
+ return plan;
257
+ }
258
+ /** Reason text for the diagnostic. */
259
+ export function explainBail(reason) {
260
+ switch (reason) {
261
+ case 'rest':
262
+ return 'this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters';
263
+ case 'computed':
264
+ return 'the property is not known until it runs';
265
+ case 'reassigned':
266
+ return 'the binding is assigned to, and props are read-only';
267
+ case 'shadowed':
268
+ return 'an inner scope binds the same name';
269
+ case 'unsafe-default':
270
+ return 'the default would have to run again on every read';
271
+ }
272
+ }
@@ -0,0 +1 @@
1
+ function u(s,n){if(s)switch(s.type){case"Identifier":n.add(s.name);return;case"ObjectPattern":for(let e of s.properties)e.type==="RestElement"?u(e.argument,n):u(e.value,n);return;case"ArrayPattern":for(let e of s.elements)u(e,n);return;case"AssignmentPattern":u(s.left,n);return;case"RestElement":u(s.argument,n);return}}function p(s){switch(s.type){case"StringLiteral":case"NumericLiteral":case"BooleanLiteral":case"NullLiteral":case"BigIntLiteral":case"RegExpLiteral":case"Identifier":return!0;case"Literal":return!0;case"TemplateLiteral":return s.expressions.every(p);case"UnaryExpression":return p(s.argument);case"MemberExpression":return!1;default:return!1}}function f(s,n){if(!(!s||typeof s!="object")){n(s);for(let e of Object.keys(s)){if(e==="loc"||e==="range"||e==="leadingComments"||e==="trailingComments")continue;let t=s[e];if(Array.isArray(t))for(let a of t)a&&typeof a=="object"&&f(a,n);else t&&typeof t=="object"&&typeof t.type=="string"&&f(t,n)}}}function y(s){let n=new Set;return f(s,e=>{if(e.type==="AssignmentExpression")u(e.left,n);else if(e.type==="UpdateExpression"){let t=e.argument;t?.type==="Identifier"&&n.add(t.name)}}),n}function h(s,n){let e=new Set,t=a=>{let c=new Set;u(a,c);for(let i of c)n.has(i)&&e.add(i)};return f(s,a=>{switch(a.type){case"VariableDeclarator":t(a.id);return;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":t(a.id);for(let c of a.params??[])t(c);return;case"CatchClause":t(a.param);return;case"ClassDeclaration":case"ClassExpression":t(a.id);return}}),e}function g(s,n,e){for(let t of s.properties??[]){if(t.type==="RestElement"){let o=t.argument;if(o?.type!=="Identifier"||n.length>0){let l=new Set;u(o,l);for(let N of l)e.bails.push({name:N,reason:"rest"});continue}e.rest={name:o.name,keys:[]};continue}if(t.computed){let o=new Set;u(t.value,o);for(let l of o)e.bails.push({name:l,reason:"computed"});continue}let a=t.key,c=a.type==="Identifier"?a.name:a.value,i=t.value,r;i.type==="AssignmentPattern"&&(r=i.right,i=i.left);let d=[...n,c];if(i.type==="Identifier"){if(r&&!p(r)){e.bails.push({name:i.name,reason:"unsafe-default"});continue}e.reads.push({name:i.name,path:d,...r?{fallback:r}:{}});continue}if(i.type==="ObjectPattern"){if(r){let o=new Set;u(i,o);for(let l of o)e.bails.push({name:l,reason:"unsafe-default"});continue}g(i,d,e);continue}let m=new Set;u(i,m);for(let o of m)e.bails.push({name:o,reason:"computed"})}}function w(s,n){let e={reads:[],bails:[]};if(s?.type!=="ObjectPattern"||(g(s,[],e),e.rest&&(n?.type!=="BlockStatement"?(e.bails.push({name:e.rest.name,reason:"rest"}),delete e.rest):e.rest.keys=(s.properties??[]).filter(r=>r.type!=="RestElement"&&!r.computed).map(r=>{let d=r.key;return d.type==="Identifier"?d.name:d.value})),e.reads.length===0&&!e.rest))return e;let t=new Set(e.reads.map(r=>r.name));e.rest&&t.add(e.rest.name);let a=y(n),c=h(n,t),i=[];for(let r of e.reads)a.has(r.name)?e.bails.push({name:r.name,reason:"reassigned"}):c.has(r.name)?e.bails.push({name:r.name,reason:"shadowed"}):i.push(r);return e.reads=i,e.rest&&a.has(e.rest.name)?(e.bails.push({name:e.rest.name,reason:"reassigned"}),delete e.rest):e.rest&&c.has(e.rest.name)&&(e.bails.push({name:e.rest.name,reason:"shadowed"}),delete e.rest),e}function b(s){switch(s){case"rest":return"this rest element cannot be served by splitProps, and copying the props into a plain object would lose the getters";case"computed":return"the property is not known until it runs";case"reassigned":return"the binding is assigned to, and props are read-only";case"shadowed":return"an inner scope binds the same name";case"unsafe-default":return"the default would have to run again on every read"}}export{b as explainBail,w as planPropsDestructure};
@@ -0,0 +1 @@
1
+ "use strict";var f=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var I=(r,e)=>{for(var i in e)f(r,i,{get:e[i],enumerable:!0})},x=(r,e,i,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of y(e))!N.call(r,n)&&n!==i&&f(r,n,{get:()=>e[n],enumerable:!(t=g(e,n))||t.enumerable});return r};var v=r=>x(f({},"__esModule",{value:!0}),r);var b={};I(b,{declaredNames:()=>E,resolveReactiveBindings:()=>w});module.exports=v(b);var o="@fluixi/reactive/signal",l={$signal:{export:"signal",module:o,returns:"signal-handle"},$memo:{export:"memo",module:o,returns:"memo-handle"},$effect:{export:"effect",module:o,returns:"effect"},$store:{export:"store",module:"@fluixi/reactive/store",returns:"store-handle"},$resource:{export:"resource",module:o,returns:"resource-handle"},$selector:{export:"createSelector",module:o,returns:"memo-accessor"},$deferred:{export:"createDeferred",module:o,returns:"memo-accessor"},$untrack:{export:"untrack",module:o,returns:"plain"},$untrackStore:{export:"untrackStore",module:"@fluixi/reactive/store",returns:"plain"}},p={signal:"signal-handle",memo:"memo-handle",effect:"effect",store:"store-handle",createSignal:["signal-accessor","signal-setter"],createMemo:"memo-accessor",createEffect:"effect",createRenderEffect:"effect",createStore:"reactive-object",resource:"resource-handle",createResource:"reactive-object",createSelector:"memo-accessor",createDeferred:"memo-accessor"},R=["@fluixi/reactive","@fluixi/reactive/signal","@fluixi/reactive/signal-next","@fluixi/reactive/store","@fluixi/core","@fluixi/core/rx"],D=new RegExp(`\\$(?:${Object.keys(l).map(r=>r.slice(1)).join("|")})\\s*\\(`);function d(r){return R.includes(r)}function s(r,e){if(r)switch(r.type){case"Identifier":e.add(r.name);return;case"ObjectPattern":for(let i of r.properties??[])i.type==="RestElement"?s(i.argument,e):s(i.value,e);return;case"ArrayPattern":for(let i of r.elements??[])s(i,e);return;case"AssignmentPattern":s(r.left,e);return;case"RestElement":s(r.argument,e);return}}function c(r,e){if(!(!r||typeof r!="object"||typeof r.type!="string")){e(r);for(let i of Object.keys(r)){if(i==="loc"||i==="leadingComments"||i==="trailingComments")continue;let t=r[i];if(Array.isArray(t))for(let n of t)c(n,e);else t&&typeof t=="object"&&c(t,e)}}}function S(r,e){if(r.type!=="CallExpression")return;let i=r.callee;if(i?.type!=="Identifier")return;let t=i.name,n=e.primitives.get(t);if(n)return n;let a=l[t];if(a&&!e.shadowed.has(t))return a.returns}function h(r,e,i){if(Array.isArray(e)){r.type==="ArrayPattern"&&r.elements.forEach((t,n)=>{let a=e[n];t?.type==="Identifier"&&a&&i.set(t.name,a)});return}r.type==="Identifier"&&i.set(r.name,e)}function E(r){let e=new Set;return c(r,i=>{switch(i.type){case"VariableDeclarator":s(i.id,e);return;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":s(i.id,e);for(let t of i.params??[])s(t,e);return;case"ClassDeclaration":case"ClassExpression":s(i.id,e);return;case"ImportSpecifier":case"ImportDefaultSpecifier":case"ImportNamespaceSpecifier":s(i.local,e);return;case"CatchClause":s(i.param,e);return}}),e}function w(r){let e={kinds:new Map,primitives:new Map,shadowed:new Set},i=r;c(i,t=>{let n=new Set;if(t.type==="VariableDeclarator")s(t.id,n);else if(t.type==="FunctionDeclaration"||t.type==="ClassDeclaration")s(t.id,n);else if(t.type==="ImportDefaultSpecifier"||t.type==="ImportNamespaceSpecifier")s(t.local,n);else if(t.type==="ImportSpecifier")s(t.local,n);else if(t.type==="FunctionExpression"||t.type==="ArrowFunctionExpression"||t.type==="FunctionDeclaration")for(let a of t.params??[])s(a,n);for(let a of n)l[a]&&e.shadowed.add(a)});for(let t of i.body??[])if(t.type==="ImportDeclaration"&&d(t.source?.value))for(let n of t.specifiers??[]){if(n.type!=="ImportSpecifier")continue;let a=n.imported,m=a.type==="Identifier"?a.name:a.value,u=p[m];u&&e.primitives.set(n.local.name,u)}return c(i,t=>{if(t.type!=="VariableDeclarator"||!t.init)return;let n=S(t.init,e);n&&h(t.id,n,e.kinds)}),e}