@fluixi/compiler 1.0.0-alpha.83 → 1.0.0-alpha.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyze/expr-shape.cjs +62 -1
- package/dist/analyze/expr-shape.d.cts +14 -0
- package/dist/analyze/expr-shape.mjs +41 -1
- package/dist/analyze/intrinsics.cjs +80 -1
- package/dist/analyze/intrinsics.d.cts +66 -0
- package/dist/analyze/intrinsics.mjs +59 -1
- 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 -1
- package/dist/analyze/props-destructure.d.cts +83 -0
- package/dist/analyze/props-destructure.mjs +205 -1
- package/dist/analyze/reactive-bindings.cjs +190 -1
- package/dist/analyze/reactive-bindings.d.cts +42 -0
- package/dist/analyze/reactive-bindings.mjs +167 -1
- package/dist/analyze/reactive-expr.cjs +38 -1
- package/dist/analyze/reactive-expr.d.cts +38 -0
- package/dist/analyze/reactive-expr.mjs +17 -1
- package/dist/analyze/static-graph.cjs +811 -1
- package/dist/analyze/static-graph.d.cts +102 -0
- package/dist/analyze/static-graph.mjs +793 -1
- package/dist/babel-NRW4EFTG.mjs +636 -0
- package/dist/chunk-3YKZ4GNH.mjs +11 -0
- package/dist/chunk-EZR7NZOY.mjs +1718 -0
- package/dist/chunk-FSSWUXUR.mjs +16 -0
- package/dist/chunk-MJV3UXIL.mjs +158 -0
- package/dist/chunk-R2VHAZAX.mjs +1078 -0
- package/dist/codegen/backend.cjs +18 -1
- package/dist/codegen/backend.d.cts +35 -0
- package/dist/codegen/backends/imperative.cjs +542 -1
- package/dist/codegen/backends/imperative.d.cts +11 -0
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +12 -8
- package/dist/codegen/backends/imperative.mjs +519 -1
- package/dist/codegen/contract.cjs +52 -1
- package/dist/codegen/contract.d.cts +24 -0
- package/dist/codegen/contract.mjs +31 -1
- package/dist/codegen/partial-template.cjs +176 -1
- package/dist/codegen/partial-template.d.cts +61 -0
- package/dist/codegen/partial-template.mjs +153 -1
- package/dist/codegen/serialize-static.cjs +125 -1
- package/dist/codegen/serialize-static.d.cts +38 -0
- package/dist/codegen/serialize-static.mjs +104 -1
- package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
- package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
- package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
- package/dist/frontend/babel/build-ir.cjs +1524 -1
- package/dist/frontend/babel/build-ir.d.cts +35 -0
- package/dist/frontend/babel/build-ir.mjs +1495 -1
- package/dist/frontend/babel/index.cjs +2186 -1
- package/dist/frontend/babel/index.d.cts +33 -0
- package/dist/frontend/babel/index.mjs +2156 -1
- package/dist/frontend/babel/lower-template.cjs +1507 -1
- package/dist/frontend/babel/lower-template.d.cts +23 -0
- package/dist/frontend/babel/lower-template.mjs +1478 -1
- package/dist/frontend/babel/plugin.cjs +2132 -1
- package/dist/frontend/babel/plugin.d.cts +95 -0
- package/dist/frontend/babel/plugin.mjs +2103 -1
- package/dist/frontend/babel/server-functions.cjs +110 -1
- package/dist/frontend/babel/server-functions.d.cts +10 -0
- package/dist/frontend/babel/server-functions.mjs +89 -1
- package/dist/frontend/babel/types.cjs +18 -1
- package/dist/frontend/babel/types.d.cts +33 -0
- package/dist/frontend/types.cjs +18 -1
- package/dist/frontend/types.d.cts +25 -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 +1594 -13
- package/dist/index.d.cts +27 -0
- package/dist/index.mjs +1574 -13
- package/dist/integrations.cjs +4307 -25
- package/dist/integrations.d.cts +215 -0
- package/dist/integrations.mjs +531 -17
- package/dist/ir/nodes.cjs +18 -1
- package/dist/ir/nodes.d.cts +168 -0
- package/dist/lower/compile-template.cjs +1356 -1
- package/dist/lower/compile-template.d.cts +69 -0
- package/dist/lower/compile-template.mjs +1336 -1
- package/dist/lower/jsx.cjs +529 -1
- package/dist/lower/jsx.d.cts +25 -0
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +2 -1
- package/dist/lower/jsx.mjs +506 -1
- package/dist/lower/template.cjs +1061 -1
- package/dist/lower/template.d.cts +53 -0
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +5 -4
- package/dist/lower/template.mjs +1042 -1
- package/dist/lower/text.cjs +42 -1
- package/dist/lower/text.d.cts +10 -0
- package/dist/lower/text.mjs +21 -1
- package/dist/optimize/analyze-static.cjs +112 -1
- package/dist/optimize/analyze-static.d.cts +39 -0
- package/dist/optimize/analyze-static.mjs +91 -1
- package/dist/optimize/collapse-strategies.cjs +90 -1
- package/dist/optimize/collapse-strategies.d.cts +30 -0
- package/dist/optimize/collapse-strategies.mjs +67 -1
- package/dist/options.cjs +33 -1
- package/dist/options.d.cts +39 -0
- package/dist/options.mjs +12 -1
- package/dist/resolve/builtins.cjs +73 -1
- package/dist/resolve/builtins.d.cts +68 -0
- package/dist/resolve/builtins.mjs +53 -1
- package/dist/resolve/component-globals.cjs +233 -13
- package/dist/resolve/component-globals.d.cts +80 -0
- package/dist/resolve/component-globals.mjs +210 -13
- package/dist/resolve/component-resolver.cjs +80 -1
- package/dist/resolve/component-resolver.d.cts +68 -0
- package/dist/resolve/component-resolver.mjs +59 -1
- package/dist/resolve/load-directive.cjs +93 -1
- package/dist/resolve/load-directive.d.cts +53 -0
- package/dist/resolve/load-directive.mjs +72 -1
- package/dist/resolve/resolve-ir.cjs +108 -1
- package/dist/resolve/resolve-ir.d.cts +53 -0
- package/dist/resolve/resolve-ir.mjs +85 -1
- package/dist/resolve/write-globals.cjs +318 -13
- package/dist/resolve/write-globals.d.cts +30 -0
- package/dist/resolve/write-globals.mjs +297 -13
- package/dist/server-fns-4ZXN6DYU.mjs +78 -0
- package/dist/server-functions-V6D6DRIA.mjs +82 -0
- package/dist/transform/bindings.cjs +71 -1
- package/dist/transform/bindings.d.cts +16 -0
- package/dist/transform/bindings.mjs +50 -1
- package/dist/transform/index.cjs +2732 -8
- package/dist/transform/index.d.cts +15 -0
- package/dist/transform/index.mjs +3773 -17
- package/dist/transform/intrinsics.cjs +216 -3
- package/dist/transform/intrinsics.d.cts +21 -0
- package/dist/transform/intrinsics.mjs +193 -3
- package/dist/transform/props.cjs +441 -3
- package/dist/transform/props.d.cts +45 -0
- package/dist/transform/props.mjs +1482 -12
- package/dist/transform/server-fn-id.cjs +35 -1
- package/dist/transform/server-fn-id.d.cts +9 -0
- package/dist/transform/server-fn-id.mjs +14 -1
- package/dist/transform/server-fns.cjs +114 -2
- package/dist/transform/server-fns.d.cts +12 -0
- package/dist/transform/server-fns.mjs +1155 -11
- package/dist/transform/source-locations.cjs +330 -1
- package/dist/transform/source-locations.d.cts +43 -0
- package/dist/transform/source-locations.mjs +307 -1
- package/dist/transform/templates.cjs +2701 -7
- package/dist/transform/templates.d.cts +69 -0
- package/dist/transform/templates.mjs +3743 -16
- package/dist/transform-BT4MMASR.mjs +893 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/dist/babel-VXKH6MRQ.mjs +0 -1
- package/dist/chunk-3SAEGOMQ.mjs +0 -1
- package/dist/chunk-5KMMN5QP.mjs +0 -1
- package/dist/chunk-IBRM4W7I.mjs +0 -10
- package/dist/chunk-OHHZCYIQ.mjs +0 -1
- package/dist/chunk-YKZ54NVE.mjs +0 -1
- package/dist/server-fns-6QM243HC.mjs +0 -2
- package/dist/server-functions-E3LKCZ4R.mjs +0 -1
- package/dist/transform-C4ZXRVGP.mjs +0 -8
|
@@ -1 +1,793 @@
|
|
|
1
|
-
import{parse as De}from"@babel/parser";import{parseTemplate as Me}from"@fluixi/template-parser";var L="@fluixi/reactive/signal",W={$signal:{export:"signal",module:L,returns:"signal-handle"},$memo:{export:"memo",module:L,returns:"memo-handle"},$effect:{export:"effect",module:L,returns:"effect"},$store:{export:"store",module:"@fluixi/reactive/store",returns:"store-handle"},$resource:{export:"resource",module:L,returns:"resource-handle"},$selector:{export:"createSelector",module:L,returns:"memo-accessor"},$deferred:{export:"createDeferred",module:L,returns:"memo-accessor"},$untrack:{export:"untrack",module:L,returns:"plain"},$untrackStore:{export:"untrackStore",module:"@fluixi/reactive/store",returns:"plain"}},de={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"},Re=["@fluixi/reactive","@fluixi/reactive/signal","@fluixi/reactive/store","@fluixi/core"],Ve=new RegExp(`\\$(?:${Object.keys(W).map(t=>t.slice(1)).join("|")})\\s*\\(`);function ue(t){return Object.prototype.hasOwnProperty.call(W,t)}function le(t){return Re.includes(t)}function T(t,i){if(t)switch(t.type){case"Identifier":i.add(t.name);return;case"ObjectPattern":for(let r of t.properties??[])r.type==="RestElement"?T(r.argument,i):T(r.value,i);return;case"ArrayPattern":for(let r of t.elements??[])T(r,i);return;case"AssignmentPattern":T(t.left,i);return;case"RestElement":T(t.argument,i);return}}function G(t,i){if(!(!t||typeof t!="object"||typeof t.type!="string")){i(t);for(let r of Object.keys(t)){if(r==="loc"||r==="leadingComments"||r==="trailingComments")continue;let e=t[r];if(Array.isArray(e))for(let o of e)G(o,i);else e&&typeof e=="object"&&G(e,i)}}}function we(t,i){if(t.type!=="CallExpression")return;let r=t.callee;if(r?.type!=="Identifier")return;let e=r.name,o=i.primitives.get(e);if(o)return o;let a=W[e];if(a&&!i.shadowed.has(e))return a.returns}function ke(t,i,r){if(Array.isArray(i)){t.type==="ArrayPattern"&&t.elements.forEach((e,o)=>{let a=i[o];e?.type==="Identifier"&&a&&r.set(e.name,a)});return}t.type==="Identifier"&&r.set(t.name,i)}function fe(t){let i={kinds:new Map,primitives:new Map,shadowed:new Set},r=t;G(r,e=>{let o=new Set;if(e.type==="VariableDeclarator")T(e.id,o);else if(e.type==="FunctionDeclaration"||e.type==="ClassDeclaration")T(e.id,o);else if(e.type==="ImportDefaultSpecifier"||e.type==="ImportNamespaceSpecifier")T(e.local,o);else if(e.type==="ImportSpecifier")T(e.local,o);else if(e.type==="FunctionExpression"||e.type==="ArrowFunctionExpression"||e.type==="FunctionDeclaration")for(let a of e.params??[])T(a,o);for(let a of o)W[a]&&i.shadowed.add(a)});for(let e of r.body??[])if(e.type==="ImportDeclaration"&&le(e.source?.value))for(let o of e.specifiers??[]){if(o.type!=="ImportSpecifier")continue;let a=o.imported,I=a.type==="Identifier"?a.name:a.value,D=de[I];D&&i.primitives.set(o.local.name,D)}return G(r,e=>{if(e.type!=="VariableDeclarator"||!e.init)return;let o=we(e.init,i);o&&ke(e.id,o,i.kinds)}),i}var H=["Show","For","Index","Switch","Match","Portal","Dynamic","ErrorBoundary"],q=["Suspense","SuspenseList","Await"],z=["Router","Outlet","Redirect","Link"],Xe=[...H,...q,...z],We=new Set([...H,...q]);var Oe={signal:"state",createSignal:"state",memo:"memo",createMemo:"memo",effect:"effect",createEffect:"effect",store:"store",createStore:"store",resource:"resource",createResource:"resource"},Te=new Set(["memo","effect","resource"]),pe=new Set([...H,...q,...z]),me={Router:"routes",Link:"href",Redirect:"to",Show:"when",Match:"when",For:"each",Index:"each",Dynamic:"component",Portal:"mount",Await:"value"},Ce=new Set(z),ge=t=>Ce.has(t)?"router":"control",Pe=new Set(["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"]);function Ae(t){return t.replace(/\\/g,"/").replace(/^\.?\/+/,"")}function M(t,i,r=[]){if(!(!t||typeof t.type!="string")){i(t,r),r.push(t);for(let e of Object.keys(t)){if(e==="loc"||e==="parent")continue;let o=t[e];if(Array.isArray(o))for(let a of o)M(a,i,r);else o&&typeof o.type=="string"&&M(o,i,r)}r.pop()}}function $e(t){let r=[...t].reverse().find(e=>e.type==="VariableDeclarator")?.id;if(r?.type==="Identifier")return r.name;if(r?.type==="ArrayPattern"){let e=r.elements?.[0];if(e?.type==="Identifier")return e.name}}function je(t){if(t.type==="FunctionDeclaration"){let i=t.id?.name;return i&&i[0]===i[0]?.toUpperCase()?i:void 0}if(t.type==="VariableDeclarator"){let i=t.id,r=t.init;if(i?.type!=="Identifier"||!r||r.type!=="ArrowFunctionExpression"&&r.type!=="FunctionExpression")return;let e=i.name;return e[0]===e[0]?.toUpperCase()?e:void 0}}function B(t){let i=new Set;return M(t,(r,e)=>{if(r.type!=="Identifier")return;let o=e[e.length-1];o?.type==="MemberExpression"&&o.property===r&&!o.computed||o?.type==="ObjectProperty"&&o.key===r&&!o.computed||i.add(r.name)}),i}function Fe(t){let i=[],r=t.quasis??[],e=t.expressions??[];return r.forEach((o,a)=>{let I=o.value;if(i.push({kind:"static",text:I?.cooked??I?.raw??"",start:o.start??0}),a<e.length){let D=e[a];i.push({kind:"hole",index:a,start:D.start??0,end:D.end??0})}}),i}function _e(t){let i=[0];for(let r=0;r<t.length;r++)t.charCodeAt(r)===10&&i.push(r+1);return r=>{let e=0,o=i.length-1;for(;e<o;){let a=e+o+1>>1;i[a]<=r?e=a:o=a-1}return{line:e+1,column:r-i[e]}}}function he(t){let i="",r=[];for(let e of t.attributes)e.kind!=="Attribute"||e.value?.kind!=="static"||(e.name==="id"?i=`#${e.value.value}`:e.name==="class"&&r.push(...String(e.value.value).split(/\s+/).filter(Boolean).slice(0,2)));return`${t.tag}${i}${r.map(e=>`.${e}`).join("")}`}function Ne(t){return t?t.kind==="hole"?[t.hole]:t.kind==="mixed"?t.parts.flatMap(i=>"hole"in i?[i.hole]:[]):[]:[]}function ye(t){let i=t.name?.name??"element",r="",e=[];for(let o of t.attributes??[]){if(o.type!=="JSXAttribute")continue;let a=o.name?.name,I=o.value;I?.type==="StringLiteral"&&(a==="id"?r=`#${I.value}`:(a==="class"||a==="className")&&e.push(...String(I.value).split(/\s+/).filter(Boolean).slice(0,2)))}return`${i}${r}${e.map(o=>`.${o}`).join("")}`}function Le(t,i){for(let r of t.attributes??[]){if(r.type!=="JSXAttribute"||r.name?.name!==i)continue;let e=r.value;return e?.type==="JSXExpressionContainer"?e.expression:void 0}}function et(t,i={}){let r=(i.routesDir??"src/routes").replace(/^\.?\/+|\/+$/g,""),e=(i.apiDir??"src/api").replace(/^\.?\/+|\/+$/g,""),o=[],a=[],I=new Map,D=new Map,F=new Map,Q=[],te=[],Y=[],Z=new Map,ne=[],re=new Map,J=0;for(let n of t){if(!/\.(tsx?|jsx?)$/.test(n.path))continue;let s;try{s=De(n.code,{sourceType:"module",plugins:["jsx","typescript"],errorRecovery:!0}).program}catch{continue}let{primitives:g,shadowed:R}=fe(s),w=new Map,A=new Map,x=new Map;D.set(n.path,w),I.set(n.path,A),F.set(n.path,x);let Se=Ae(n.path).startsWith(`${r}/`),_=new Map,xe=null,ve=()=>xe??=_e(n.code);M(s,(c,f)=>{let d=je(c),u=c.loc?.start;if(!d||!u)return;let N=J++;_.set(c,N),w.set(d,N),re.set(N,B(c)),Se&&o.push(N),a.push({node:{id:N,label:d,kind:Pe.has(d)?"handler":"component",deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:u.line,column:u.column}},reads:new Set,file:n.path})}),M(s,(c,f)=>{if(c.type==="ImportDeclaration"){let k=c.source?.value;for(let V of c.specifiers??[]){let $=V.local?.name;$&&k?.startsWith(".")&&x.set($,k)}return}if(c.type!=="CallExpression")return;let d=c.callee;if(d?.type!=="Identifier")return;let u=d.name,N=u.startsWith("$")&&ue(u)&&!R.has(u);if(!N&&!g.has(u))return;let l=Oe[N?u.slice(1):u],p=c.loc?.start;if(!l||!p)return;let y=J++,C=$e(f)??`${l}${y}`;w.set(C,y);let E;for(let k=f.length-1;k>=0;k--){let V=_.get(f[k]);if(V!==void 0){E=V;break}}a.push({node:{id:y,label:C,kind:l,deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:p.line,column:p.column},...E!==void 0?{createdIn:E}:{}},reads:Te.has(l)?B(c.arguments?.[0]):new Set,file:n.path})}),M(s,(c,f)=>{if(c.type!=="JSXOpeningElement")return;let d=c.name?.name;if(!d||d[0]!==d[0]?.toUpperCase())return;let u;for(let l=f.length-1;l>=0;l--){let p=_.get(f[l]);if(p!==void 0){u=p;break}}if(!(w.has(d)||x.has(d))&&pe.has(d)){let l=c.loc?.start;if(!l)return;let p=J++,y=me[d],C=y?Le(c,y):void 0,E=f[f.length-1];E?.type==="JSXElement"&&_.set(E,p),a.push({node:{id:p,label:d,kind:ge(d),deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:l.line,column:l.column},...u!==void 0?{createdIn:u}:{}},reads:C?B(C):new Set,file:n.path});return}u!==void 0&&Q.push({tag:d,file:n.path,owner:u})}),M(s,(c,f)=>{if(c.type!=="JSXExpressionContainer")return;let d=c.expression;if(!d||d.type==="JSXEmptyExpression")return;let u=d.loc?.start;if(!u)return;let N=f[f.length-1],l=N?.type==="JSXAttribute"?N.name?.name:void 0,p=[...f].reverse().find(E=>E.type==="JSXElement"||E.type==="JSXOpeningElement"),y=p?.type==="JSXOpeningElement"?p:p?.openingElement;if(!y)return;let C={kind:l?"attribute":"content",...l?{name:l}:{},element:ye(y),source:{file:n.path,line:u.line,column:u.column}};for(let E of B(d))Y.push({file:n.path,name:E,target:C})});let se=c=>{let f=c.openingElement??void 0,d=f?.name?.name;if(!f||!d)return;let u=c.loc?.start,N=u?{file:n.path,line:u.line,column:u.column}:void 0,l=[];for(let p of c.children??[]){if(p?.type!=="JSXElement")continue;let y=se(p);y&&l.push(y)}if(d[0]===d[0]?.toUpperCase()){let p={label:d,children:l,...N?{at:N}:{}},y=_.get(c)??w.get(d);return y!==void 0?p.owner=y:ne.push({node:p,tag:d,file:n.path}),p}return{label:ye(f),children:l,...N?{at:N}:{}}};M(s,(c,f)=>{if(c.type!=="JSXElement")return;let d;for(let l=f.length-1;l>=0;l--){let p=f[l];if(p.type==="JSXElement")return;let y=_.get(p);if(y!==void 0){d=y;break}}if(d===void 0)return;let u=se(c);if(!u)return;let N=Z.get(d);N?N.push(u):Z.set(d,[u])}),M(s,(c,f)=>{if(c.type!=="TaggedTemplateExpression")return;let d=c.tag?.name;if(d!=="html"&&d!=="svg")return;let u=c.quasi,N=u?.expressions??[],l=ve(),p;try{p=Me(Fe(u),{svg:d==="svg"}).root.children}catch{return}let y=v=>v==null?void 0:N[v],C=v=>{let m=y(v);return m?B(m):new Set},E=(v,m,b,h)=>{let S=m!==void 0?l(m):y(b)?.loc?.start??c.loc?.start;if(!S)return;let P=J++;return a.push({node:{id:P,label:v,kind:ge(v),deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:S.line,column:S.column},...h!==void 0?{createdIn:h}:{}},reads:C(b),file:n.path}),P},k=(v,m,b)=>{let h=y(v),S=h?.loc?.start;if(!h||!S)return;let P={kind:b?"attribute":"content",...b?{name:b}:{},element:m,source:{file:n.path,line:S.line,column:S.column}};for(let j of B(h))Y.push({file:n.path,name:j,target:P})},V=v=>{let m=he(v);for(let b of v.attributes)switch(b.kind){case"Attribute":for(let h of Ne(b.value))k(h,m,b.name);break;case"PropertyBinding":case"BindDirective":k(b.hole,m,b.name);break;case"ClassDirective":k(b.hole,m,"class");break;case"StyleDirective":k(b.hole,m,"style");break;default:break}},$=(v,m,b)=>{for(let h of v)switch(h.kind){case"Element":{let S=h.attributes.find(O=>O.kind==="IfDirective"),P=h.attributes.find(O=>O.kind==="EachDirective"),j=m;S?.kind==="IfDirective"?j=E("Show",h.loc?.start,S.hole,m)??m:P?.kind==="EachDirective"&&(j=E("For",h.loc?.start,P.hole,m)??m),V(h),$(h.children,j,he(h));break}case"Component":{let S=h.tag,P=w.has(S)||x.has(S);if(S&&!P&&pe.has(S)){let j=me[S],O=j?h.attributes.find(ce=>"name"in ce&&ce.name===j):void 0,Ie=O&&"hole"in O?O.hole:O&&"value"in O?Ne(O.value)[0]:void 0,Ee=E(S,h.loc?.start,Ie,m);$(h.children,Ee??m,b);break}S&&m!==void 0&&Q.push({tag:S,file:n.path,owner:m}),$(h.children,m,b);break}case"Fragment":$(h.children,m,b);break;case"Expression":k(h.hole,b,void 0);break;default:break}},ae;for(let v=f.length-1;v>=0;v--){let m=_.get(f[v]);if(m!==void 0){ae=m;break}}$(p,ae,"template")}),M(s,(c,f)=>{if(c.type!=="ObjectProperty"||c.computed)return;let d=c.key?.name??c.key?.value;if(d!=="component"&&d!=="Component")return;let u=c.value;if(u?.type!=="Identifier")return;let l=[...f].reverse().find(p=>p.type==="VariableDeclarator")?.id?.name;l&&te.push({via:l,tag:u.name,file:n.path})}),M(s,c=>{if(!(c.type!=="ExportNamedDeclaration"&&c.type!=="ExportDefaultDeclaration"))for(let f of w.keys())A.set(f,w.get(f))})}let U=(n,s)=>{let g=D.get(n)?.get(s);if(g!==void 0)return g;let R=F.get(n)?.get(s);if(R)for(let[w,A]of I){if(!Ke(n,R,w))continue;let x=A.get(s);if(x!==void 0)return x}};for(let n of a){let s=new Set;for(let g of n.reads){let R=U(n.file,g);R!==void 0&&R!==n.node.id&&s.add(R)}n.node.deps=[...s]}let X=new Map;for(let n of I.values())for(let[s,g]of n)X.set(s,X.has(s)?null:g);let K=new Map(a.map(n=>[n.node.id,n.node]));for(let n of ne){let s=U(n.file,n.tag)??X.get(n.tag)??void 0;s!==void 0&&K.get(s)?.kind==="component"&&(n.node.owner=s)}for(let[n,s]of Z){let g=K.get(n);g&&s.length&&(g.dom=s)}for(let n of Y){let s=U(n.file,n.name),g=s!==void 0?K.get(s):void 0;!g||g.kind==="component"||(g.targets??=[]).push(n.target)}for(let n of te){let s=U(n.file,n.tag)??X.get(n.tag)??void 0;if(s===void 0)continue;let g=a.find(x=>x.file===n.file&&x.node.kind==="router"&&x.node.id!==s&&x.reads.has(n.via))?.node.id,R=a.find(x=>x.file===n.file&&(x.node.kind==="component"||x.node.kind==="handler")&&x.node.id!==s&&re.get(x.node.id)?.has(n.via))?.node.id,w=g??R,A=K.get(s);A&&A.createdIn===void 0&&w!==void 0&&(A.createdIn=w)}for(let n of Q){let s=U(n.file,n.tag)??X.get(n.tag)??void 0;if(s===void 0||s===n.owner)continue;let g=K.get(s);g&&g.kind==="component"&&g.createdIn===void 0&&(g.createdIn=n.owner)}let ie=(n,s)=>{let g=a.filter(R=>R.node.kind===n&&R.node.label===s);return g.length===1?g[0].node.id:void 0},ee=ie("router","Outlet")??ie("router","Router");if(ee!==void 0)for(let n of o){let s=K.get(n);s&&s.kind==="component"&&s.createdIn===void 0&&n!==ee&&(s.createdIn=ee)}let oe=a.filter(n=>n.node.kind==="handler"&&n.node.createdIn===void 0);if(oe.length>0){let n=J++;a.push({node:{id:n,label:"api",kind:"handler",deps:[],writes:[],runs:0,lastPulse:0,source:{file:e,line:1,column:0}},reads:new Set,file:e});for(let s of oe)s.node.createdIn=n}return{t:Date.now(),nodes:a.map(n=>n.node),static:!0}}var be=t=>t.replace(/\.(tsx?|jsx?|mts|cts|mjs|cjs)$/,"");function Ke(t,i,r){let e=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",o=(e?e.split("/"):[]).concat(i.split("/")),a=[];for(let F of o)F==="."||F===""||(F===".."?a.pop():a.push(F));let I=be(a.join("/")),D=be(r);return D===I||D===`${I}/index`}export{et as analyzeReactiveGraph};
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.84 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
|
+
|
|
3
|
+
// src/analyze/static-graph.ts
|
|
4
|
+
import { parse } from "@babel/parser";
|
|
5
|
+
import {
|
|
6
|
+
parseTemplate
|
|
7
|
+
} from "@fluixi/template-parser";
|
|
8
|
+
|
|
9
|
+
// src/analyze/intrinsics.ts
|
|
10
|
+
var REACTIVE_MODULE = "@fluixi/reactive/signal";
|
|
11
|
+
var INTRINSICS = {
|
|
12
|
+
$signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
|
|
13
|
+
$memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
|
|
14
|
+
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
15
|
+
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
16
|
+
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
17
|
+
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
18
|
+
// name. Still worth having — no import to write — and when a shorter form is
|
|
19
|
+
// designed, the change is this line rather than a compiler pass.
|
|
20
|
+
$selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
21
|
+
$deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
22
|
+
// Not value constructors, but the compiler has to know them: they change what a read
|
|
23
|
+
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
24
|
+
// dependency analysis must not guess at.
|
|
25
|
+
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
26
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
27
|
+
};
|
|
28
|
+
var RUNTIME_PRIMITIVES = {
|
|
29
|
+
signal: "signal-handle",
|
|
30
|
+
memo: "memo-handle",
|
|
31
|
+
effect: "effect",
|
|
32
|
+
store: "store-handle",
|
|
33
|
+
createSignal: ["signal-accessor", "signal-setter"],
|
|
34
|
+
createMemo: "memo-accessor",
|
|
35
|
+
createEffect: "effect",
|
|
36
|
+
createRenderEffect: "effect",
|
|
37
|
+
createStore: "reactive-object",
|
|
38
|
+
resource: "resource-handle",
|
|
39
|
+
createResource: "reactive-object",
|
|
40
|
+
createSelector: "memo-accessor",
|
|
41
|
+
createDeferred: "memo-accessor"
|
|
42
|
+
};
|
|
43
|
+
var PRIMITIVE_MODULES = [
|
|
44
|
+
"@fluixi/reactive",
|
|
45
|
+
"@fluixi/reactive/signal",
|
|
46
|
+
"@fluixi/reactive/store",
|
|
47
|
+
"@fluixi/core"
|
|
48
|
+
];
|
|
49
|
+
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
50
|
+
function isIntrinsicName(name) {
|
|
51
|
+
return Object.prototype.hasOwnProperty.call(INTRINSICS, name);
|
|
52
|
+
}
|
|
53
|
+
function isPrimitiveModule(source) {
|
|
54
|
+
return PRIMITIVE_MODULES.includes(source);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/analyze/reactive-bindings.ts
|
|
58
|
+
function patternNames(node, out) {
|
|
59
|
+
if (!node) return;
|
|
60
|
+
switch (node.type) {
|
|
61
|
+
case "Identifier":
|
|
62
|
+
out.add(node.name);
|
|
63
|
+
return;
|
|
64
|
+
case "ObjectPattern":
|
|
65
|
+
for (const p of node.properties ?? []) {
|
|
66
|
+
if (p.type === "RestElement") patternNames(p.argument, out);
|
|
67
|
+
else patternNames(p.value, out);
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
case "ArrayPattern":
|
|
71
|
+
for (const e of node.elements ?? []) patternNames(e, out);
|
|
72
|
+
return;
|
|
73
|
+
case "AssignmentPattern":
|
|
74
|
+
patternNames(node.left, out);
|
|
75
|
+
return;
|
|
76
|
+
case "RestElement":
|
|
77
|
+
patternNames(node.argument, out);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function walk(root, visit) {
|
|
82
|
+
if (!root || typeof root !== "object" || typeof root.type !== "string") return;
|
|
83
|
+
visit(root);
|
|
84
|
+
for (const key of Object.keys(root)) {
|
|
85
|
+
if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
|
|
86
|
+
const value = root[key];
|
|
87
|
+
if (Array.isArray(value)) for (const item of value) walk(item, visit);
|
|
88
|
+
else if (value && typeof value === "object") walk(value, visit);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function calledPrimitive(node, bindings) {
|
|
92
|
+
if (node.type !== "CallExpression") return void 0;
|
|
93
|
+
const callee = node.callee;
|
|
94
|
+
if (callee?.type !== "Identifier") return void 0;
|
|
95
|
+
const name = callee.name;
|
|
96
|
+
const imported = bindings.primitives.get(name);
|
|
97
|
+
if (imported) return imported;
|
|
98
|
+
const intrinsic = INTRINSICS[name];
|
|
99
|
+
if (intrinsic && !bindings.shadowed.has(name)) return intrinsic.returns;
|
|
100
|
+
return void 0;
|
|
101
|
+
}
|
|
102
|
+
function classify(id, returns, kinds) {
|
|
103
|
+
if (Array.isArray(returns)) {
|
|
104
|
+
if (id.type === "ArrayPattern") {
|
|
105
|
+
id.elements.forEach((element, index) => {
|
|
106
|
+
const kind = returns[index];
|
|
107
|
+
if (element?.type === "Identifier" && kind) kinds.set(element.name, kind);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (id.type === "Identifier") kinds.set(id.name, returns);
|
|
113
|
+
}
|
|
114
|
+
function resolveReactiveBindings(program) {
|
|
115
|
+
const bindings = { kinds: /* @__PURE__ */ new Map(), primitives: /* @__PURE__ */ new Map(), shadowed: /* @__PURE__ */ new Set() };
|
|
116
|
+
const root = program;
|
|
117
|
+
walk(root, (node) => {
|
|
118
|
+
const names = /* @__PURE__ */ new Set();
|
|
119
|
+
if (node.type === "VariableDeclarator") patternNames(node.id, names);
|
|
120
|
+
else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") patternNames(node.id, names);
|
|
121
|
+
else if (node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier") patternNames(node.local, names);
|
|
122
|
+
else if (node.type === "ImportSpecifier") patternNames(node.local, names);
|
|
123
|
+
else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration") {
|
|
124
|
+
for (const p of node.params ?? []) patternNames(p, names);
|
|
125
|
+
}
|
|
126
|
+
for (const name of names) if (INTRINSICS[name]) bindings.shadowed.add(name);
|
|
127
|
+
});
|
|
128
|
+
for (const statement of root.body ?? []) {
|
|
129
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
130
|
+
if (!isPrimitiveModule(statement.source?.value)) continue;
|
|
131
|
+
for (const specifier of statement.specifiers ?? []) {
|
|
132
|
+
if (specifier.type !== "ImportSpecifier") continue;
|
|
133
|
+
const importedNode = specifier.imported;
|
|
134
|
+
const imported = importedNode.type === "Identifier" ? importedNode.name : importedNode.value;
|
|
135
|
+
const returns = RUNTIME_PRIMITIVES[imported];
|
|
136
|
+
if (returns) bindings.primitives.set(specifier.local.name, returns);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
walk(root, (node) => {
|
|
140
|
+
if (node.type !== "VariableDeclarator" || !node.init) return;
|
|
141
|
+
const returns = calledPrimitive(node.init, bindings);
|
|
142
|
+
if (returns) classify(node.id, returns, bindings.kinds);
|
|
143
|
+
});
|
|
144
|
+
return bindings;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/resolve/builtins.ts
|
|
148
|
+
var DOM_CONTROL_FLOW = [
|
|
149
|
+
"Show",
|
|
150
|
+
"For",
|
|
151
|
+
"Index",
|
|
152
|
+
"Switch",
|
|
153
|
+
"Match",
|
|
154
|
+
"Portal",
|
|
155
|
+
"Dynamic",
|
|
156
|
+
"ErrorBoundary"
|
|
157
|
+
];
|
|
158
|
+
var CORE_CONTROL_FLOW = ["Suspense", "SuspenseList", "Await"];
|
|
159
|
+
var ROUTER_COMPONENTS = ["Router", "Outlet", "Redirect", "Link"];
|
|
160
|
+
var BUILTIN_COMPONENTS = [
|
|
161
|
+
...DOM_CONTROL_FLOW,
|
|
162
|
+
...CORE_CONTROL_FLOW,
|
|
163
|
+
...ROUTER_COMPONENTS
|
|
164
|
+
];
|
|
165
|
+
var RESERVED_COMPONENTS = /* @__PURE__ */ new Set([
|
|
166
|
+
...DOM_CONTROL_FLOW,
|
|
167
|
+
...CORE_CONTROL_FLOW
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
// src/analyze/static-graph.ts
|
|
171
|
+
var PRIMITIVE_KIND = {
|
|
172
|
+
signal: "state",
|
|
173
|
+
createSignal: "state",
|
|
174
|
+
memo: "memo",
|
|
175
|
+
createMemo: "memo",
|
|
176
|
+
effect: "effect",
|
|
177
|
+
createEffect: "effect",
|
|
178
|
+
store: "store",
|
|
179
|
+
createStore: "store",
|
|
180
|
+
resource: "resource",
|
|
181
|
+
createResource: "resource"
|
|
182
|
+
};
|
|
183
|
+
var READS = /* @__PURE__ */ new Set(["memo", "effect", "resource"]);
|
|
184
|
+
var DIRECTIVES = /* @__PURE__ */ new Set([
|
|
185
|
+
...DOM_CONTROL_FLOW,
|
|
186
|
+
...CORE_CONTROL_FLOW,
|
|
187
|
+
// The router is supplied without an import too. Without these, an app whose root renders
|
|
188
|
+
// `<Router>` has a root component connected to nothing at all.
|
|
189
|
+
...ROUTER_COMPONENTS
|
|
190
|
+
]);
|
|
191
|
+
var TRACKED_PROP = {
|
|
192
|
+
Router: "routes",
|
|
193
|
+
Link: "href",
|
|
194
|
+
Redirect: "to",
|
|
195
|
+
Show: "when",
|
|
196
|
+
Match: "when",
|
|
197
|
+
For: "each",
|
|
198
|
+
Index: "each",
|
|
199
|
+
Dynamic: "component",
|
|
200
|
+
Portal: "mount",
|
|
201
|
+
Await: "value"
|
|
202
|
+
};
|
|
203
|
+
var ROUTER = new Set(ROUTER_COMPONENTS);
|
|
204
|
+
var directiveKind = (tag) => ROUTER.has(tag) ? "router" : "control";
|
|
205
|
+
var HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
206
|
+
"GET",
|
|
207
|
+
"POST",
|
|
208
|
+
"PUT",
|
|
209
|
+
"PATCH",
|
|
210
|
+
"DELETE",
|
|
211
|
+
"HEAD",
|
|
212
|
+
"OPTIONS"
|
|
213
|
+
]);
|
|
214
|
+
function normalizePath(path) {
|
|
215
|
+
return path.replace(/\\/g, "/").replace(/^\.?\/+/, "");
|
|
216
|
+
}
|
|
217
|
+
function walk2(node, visit, stack = []) {
|
|
218
|
+
if (!node || typeof node.type !== "string") return;
|
|
219
|
+
visit(node, stack);
|
|
220
|
+
stack.push(node);
|
|
221
|
+
for (const key of Object.keys(node)) {
|
|
222
|
+
if (key === "loc" || key === "parent") continue;
|
|
223
|
+
const value = node[key];
|
|
224
|
+
if (Array.isArray(value)) for (const child of value) walk2(child, visit, stack);
|
|
225
|
+
else if (value && typeof value.type === "string") walk2(value, visit, stack);
|
|
226
|
+
}
|
|
227
|
+
stack.pop();
|
|
228
|
+
}
|
|
229
|
+
function declaredName(stack) {
|
|
230
|
+
const declarator = [...stack].reverse().find((n) => n.type === "VariableDeclarator");
|
|
231
|
+
const id = declarator?.id;
|
|
232
|
+
if (id?.type === "Identifier") return id.name;
|
|
233
|
+
if (id?.type === "ArrayPattern") {
|
|
234
|
+
const first = id.elements?.[0];
|
|
235
|
+
if (first?.type === "Identifier") return first.name;
|
|
236
|
+
}
|
|
237
|
+
return void 0;
|
|
238
|
+
}
|
|
239
|
+
function componentName(node) {
|
|
240
|
+
if (node.type === "FunctionDeclaration") {
|
|
241
|
+
const name = node.id?.name;
|
|
242
|
+
return name && name[0] === name[0]?.toUpperCase() ? name : void 0;
|
|
243
|
+
}
|
|
244
|
+
if (node.type === "VariableDeclarator") {
|
|
245
|
+
const id = node.id;
|
|
246
|
+
const init = node.init;
|
|
247
|
+
if (id?.type !== "Identifier" || !init) return void 0;
|
|
248
|
+
if (init.type !== "ArrowFunctionExpression" && init.type !== "FunctionExpression") return void 0;
|
|
249
|
+
const name = id.name;
|
|
250
|
+
return name[0] === name[0]?.toUpperCase() ? name : void 0;
|
|
251
|
+
}
|
|
252
|
+
return void 0;
|
|
253
|
+
}
|
|
254
|
+
function mentions(node) {
|
|
255
|
+
const names = /* @__PURE__ */ new Set();
|
|
256
|
+
walk2(node, (n, stack) => {
|
|
257
|
+
if (n.type !== "Identifier") return;
|
|
258
|
+
const parent = stack[stack.length - 1];
|
|
259
|
+
if (parent?.type === "MemberExpression" && parent.property === n && !parent.computed) return;
|
|
260
|
+
if (parent?.type === "ObjectProperty" && parent.key === n && !parent.computed) return;
|
|
261
|
+
names.add(n.name);
|
|
262
|
+
});
|
|
263
|
+
return names;
|
|
264
|
+
}
|
|
265
|
+
function templatePieces(quasi) {
|
|
266
|
+
const pieces = [];
|
|
267
|
+
const quasis = quasi.quasis ?? [];
|
|
268
|
+
const expressions = quasi.expressions ?? [];
|
|
269
|
+
quasis.forEach((q, i) => {
|
|
270
|
+
const value = q.value;
|
|
271
|
+
pieces.push({ kind: "static", text: value?.cooked ?? value?.raw ?? "", start: q.start ?? 0 });
|
|
272
|
+
if (i < expressions.length) {
|
|
273
|
+
const e = expressions[i];
|
|
274
|
+
pieces.push({ kind: "hole", index: i, start: e.start ?? 0, end: e.end ?? 0 });
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return pieces;
|
|
278
|
+
}
|
|
279
|
+
function positionsIn(code) {
|
|
280
|
+
const starts = [0];
|
|
281
|
+
for (let i = 0; i < code.length; i++) if (code.charCodeAt(i) === 10) starts.push(i + 1);
|
|
282
|
+
return (offset) => {
|
|
283
|
+
let low = 0;
|
|
284
|
+
let high = starts.length - 1;
|
|
285
|
+
while (low < high) {
|
|
286
|
+
const mid = low + high + 1 >> 1;
|
|
287
|
+
if (starts[mid] <= offset) low = mid;
|
|
288
|
+
else high = mid - 1;
|
|
289
|
+
}
|
|
290
|
+
return { line: low + 1, column: offset - starts[low] };
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
function describeTemplateElement(el) {
|
|
294
|
+
let id = "";
|
|
295
|
+
const classes = [];
|
|
296
|
+
for (const attr of el.attributes) {
|
|
297
|
+
if (attr.kind !== "Attribute" || attr.value?.kind !== "static") continue;
|
|
298
|
+
if (attr.name === "id") id = `#${attr.value.value}`;
|
|
299
|
+
else if (attr.name === "class") {
|
|
300
|
+
classes.push(...String(attr.value.value).split(/\s+/).filter(Boolean).slice(0, 2));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return `${el.tag}${id}${classes.map((c) => `.${c}`).join("")}`;
|
|
304
|
+
}
|
|
305
|
+
function valueHoles(value) {
|
|
306
|
+
if (!value) return [];
|
|
307
|
+
if (value.kind === "hole") return [value.hole];
|
|
308
|
+
if (value.kind === "mixed") return value.parts.flatMap((p) => "hole" in p ? [p.hole] : []);
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
function describeJsx(opening) {
|
|
312
|
+
const tag = opening.name?.name ?? "element";
|
|
313
|
+
let id = "";
|
|
314
|
+
const classes = [];
|
|
315
|
+
for (const attr of opening.attributes ?? []) {
|
|
316
|
+
if (attr.type !== "JSXAttribute") continue;
|
|
317
|
+
const name = attr.name?.name;
|
|
318
|
+
const value = attr.value;
|
|
319
|
+
if (value?.type !== "StringLiteral") continue;
|
|
320
|
+
if (name === "id") id = `#${value.value}`;
|
|
321
|
+
else if (name === "class" || name === "className") {
|
|
322
|
+
classes.push(...String(value.value).split(/\s+/).filter(Boolean).slice(0, 2));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return `${tag}${id}${classes.map((c) => `.${c}`).join("")}`;
|
|
326
|
+
}
|
|
327
|
+
function trackedExpression(opening, prop) {
|
|
328
|
+
for (const attr of opening.attributes ?? []) {
|
|
329
|
+
if (attr.type !== "JSXAttribute" || attr.name?.name !== prop) continue;
|
|
330
|
+
const value = attr.value;
|
|
331
|
+
return value?.type === "JSXExpressionContainer" ? value.expression : void 0;
|
|
332
|
+
}
|
|
333
|
+
return void 0;
|
|
334
|
+
}
|
|
335
|
+
function analyzeReactiveGraph(files, options = {}) {
|
|
336
|
+
const routesDir = (options.routesDir ?? "src/routes").replace(/^\.?\/+|\/+$/g, "");
|
|
337
|
+
const apiDir = (options.apiDir ?? "src/api").replace(/^\.?\/+|\/+$/g, "");
|
|
338
|
+
const fileRoutes = [];
|
|
339
|
+
const pending = [];
|
|
340
|
+
const exported = /* @__PURE__ */ new Map();
|
|
341
|
+
const locals = /* @__PURE__ */ new Map();
|
|
342
|
+
const imports = /* @__PURE__ */ new Map();
|
|
343
|
+
const usages = [];
|
|
344
|
+
const routeRefs = [];
|
|
345
|
+
const holes = [];
|
|
346
|
+
const domFor = /* @__PURE__ */ new Map();
|
|
347
|
+
const unresolved = [];
|
|
348
|
+
const componentMentions = /* @__PURE__ */ new Map();
|
|
349
|
+
let seq = 0;
|
|
350
|
+
for (const file of files) {
|
|
351
|
+
if (!/\.(tsx?|jsx?)$/.test(file.path)) continue;
|
|
352
|
+
let program;
|
|
353
|
+
try {
|
|
354
|
+
program = parse(file.code, {
|
|
355
|
+
sourceType: "module",
|
|
356
|
+
plugins: ["jsx", "typescript"],
|
|
357
|
+
errorRecovery: true
|
|
358
|
+
}).program;
|
|
359
|
+
} catch {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const { primitives, shadowed } = resolveReactiveBindings(program);
|
|
363
|
+
const here = /* @__PURE__ */ new Map();
|
|
364
|
+
const sold = /* @__PURE__ */ new Map();
|
|
365
|
+
const from = /* @__PURE__ */ new Map();
|
|
366
|
+
locals.set(file.path, here);
|
|
367
|
+
exported.set(file.path, sold);
|
|
368
|
+
imports.set(file.path, from);
|
|
369
|
+
const inRoutesDir = normalizePath(file.path).startsWith(`${routesDir}/`);
|
|
370
|
+
const components = /* @__PURE__ */ new Map();
|
|
371
|
+
let positionAt = null;
|
|
372
|
+
const positionOf = () => positionAt ??= positionsIn(file.code);
|
|
373
|
+
walk2(program, (node, stack) => {
|
|
374
|
+
const name = componentName(node);
|
|
375
|
+
const at = node.loc?.start;
|
|
376
|
+
if (!name || !at) return;
|
|
377
|
+
const id = seq++;
|
|
378
|
+
components.set(node, id);
|
|
379
|
+
here.set(name, id);
|
|
380
|
+
componentMentions.set(id, mentions(node));
|
|
381
|
+
if (inRoutesDir) fileRoutes.push(id);
|
|
382
|
+
pending.push({
|
|
383
|
+
node: {
|
|
384
|
+
id,
|
|
385
|
+
label: name,
|
|
386
|
+
kind: HTTP_METHODS.has(name) ? "handler" : "component",
|
|
387
|
+
deps: [],
|
|
388
|
+
writes: [],
|
|
389
|
+
runs: 0,
|
|
390
|
+
lastPulse: 0,
|
|
391
|
+
source: { file: file.path, line: at.line, column: at.column }
|
|
392
|
+
},
|
|
393
|
+
reads: /* @__PURE__ */ new Set(),
|
|
394
|
+
file: file.path
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
walk2(program, (node, stack) => {
|
|
398
|
+
if (node.type === "ImportDeclaration") {
|
|
399
|
+
const source = node.source?.value;
|
|
400
|
+
for (const spec of node.specifiers ?? []) {
|
|
401
|
+
const local = spec.local?.name;
|
|
402
|
+
if (local && source?.startsWith(".")) from.set(local, source);
|
|
403
|
+
}
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (node.type !== "CallExpression") return;
|
|
407
|
+
const callee = node.callee;
|
|
408
|
+
if (callee?.type !== "Identifier") return;
|
|
409
|
+
const name = callee.name;
|
|
410
|
+
const intrinsic = name.startsWith("$") && isIntrinsicName(name) && !shadowed.has(name);
|
|
411
|
+
if (!intrinsic && !primitives.has(name)) return;
|
|
412
|
+
const kind = PRIMITIVE_KIND[intrinsic ? name.slice(1) : name];
|
|
413
|
+
const at = node.loc?.start;
|
|
414
|
+
if (!kind || !at) return;
|
|
415
|
+
const id = seq++;
|
|
416
|
+
const label = declaredName(stack) ?? `${kind}${id}`;
|
|
417
|
+
here.set(label, id);
|
|
418
|
+
let owner;
|
|
419
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
420
|
+
const found = components.get(stack[i]);
|
|
421
|
+
if (found !== void 0) {
|
|
422
|
+
owner = found;
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
pending.push({
|
|
427
|
+
node: {
|
|
428
|
+
id,
|
|
429
|
+
label,
|
|
430
|
+
kind,
|
|
431
|
+
deps: [],
|
|
432
|
+
writes: [],
|
|
433
|
+
runs: 0,
|
|
434
|
+
lastPulse: 0,
|
|
435
|
+
source: { file: file.path, line: at.line, column: at.column },
|
|
436
|
+
...owner !== void 0 ? { createdIn: owner } : {}
|
|
437
|
+
},
|
|
438
|
+
// Only what reads can read: a signal's initial value is not a dependency.
|
|
439
|
+
reads: READS.has(kind) ? mentions(node.arguments?.[0]) : /* @__PURE__ */ new Set(),
|
|
440
|
+
file: file.path
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
walk2(program, (node, stack) => {
|
|
444
|
+
if (node.type !== "JSXOpeningElement") return;
|
|
445
|
+
const tag = node.name?.name;
|
|
446
|
+
if (!tag || tag[0] !== tag[0]?.toUpperCase()) return;
|
|
447
|
+
let owner;
|
|
448
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
449
|
+
const found = components.get(stack[i]);
|
|
450
|
+
if (found !== void 0) {
|
|
451
|
+
owner = found;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const own = here.has(tag) || from.has(tag);
|
|
456
|
+
if (!own && DIRECTIVES.has(tag)) {
|
|
457
|
+
const at = node.loc?.start;
|
|
458
|
+
if (!at) return;
|
|
459
|
+
const id = seq++;
|
|
460
|
+
const prop = TRACKED_PROP[tag];
|
|
461
|
+
const tracked = prop ? trackedExpression(node, prop) : void 0;
|
|
462
|
+
const element = stack[stack.length - 1];
|
|
463
|
+
if (element?.type === "JSXElement") components.set(element, id);
|
|
464
|
+
pending.push({
|
|
465
|
+
node: {
|
|
466
|
+
id,
|
|
467
|
+
label: tag,
|
|
468
|
+
kind: directiveKind(tag),
|
|
469
|
+
deps: [],
|
|
470
|
+
writes: [],
|
|
471
|
+
runs: 0,
|
|
472
|
+
lastPulse: 0,
|
|
473
|
+
source: { file: file.path, line: at.line, column: at.column },
|
|
474
|
+
...owner !== void 0 ? { createdIn: owner } : {}
|
|
475
|
+
},
|
|
476
|
+
reads: tracked ? mentions(tracked) : /* @__PURE__ */ new Set(),
|
|
477
|
+
file: file.path
|
|
478
|
+
});
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
if (owner !== void 0) usages.push({ tag, file: file.path, owner });
|
|
482
|
+
});
|
|
483
|
+
walk2(program, (node, stack) => {
|
|
484
|
+
if (node.type !== "JSXExpressionContainer") return;
|
|
485
|
+
const expr = node.expression;
|
|
486
|
+
if (!expr || expr.type === "JSXEmptyExpression") return;
|
|
487
|
+
const at = expr.loc?.start;
|
|
488
|
+
if (!at) return;
|
|
489
|
+
const parent = stack[stack.length - 1];
|
|
490
|
+
const attribute = parent?.type === "JSXAttribute" ? parent.name?.name : void 0;
|
|
491
|
+
const holder = [...stack].reverse().find((n) => n.type === "JSXElement" || n.type === "JSXOpeningElement");
|
|
492
|
+
const opening = holder?.type === "JSXOpeningElement" ? holder : holder?.openingElement;
|
|
493
|
+
if (!opening) return;
|
|
494
|
+
const target = {
|
|
495
|
+
kind: attribute ? "attribute" : "content",
|
|
496
|
+
...attribute ? { name: attribute } : {},
|
|
497
|
+
element: describeJsx(opening),
|
|
498
|
+
source: { file: file.path, line: at.line, column: at.column }
|
|
499
|
+
};
|
|
500
|
+
for (const name of mentions(expr)) holes.push({ file: file.path, name, target });
|
|
501
|
+
});
|
|
502
|
+
const describeTree = (el) => {
|
|
503
|
+
const opening = el.openingElement ?? void 0;
|
|
504
|
+
const tag = opening?.name?.name;
|
|
505
|
+
if (!opening || !tag) return void 0;
|
|
506
|
+
const at = el.loc?.start;
|
|
507
|
+
const where = at ? { file: file.path, line: at.line, column: at.column } : void 0;
|
|
508
|
+
const children = [];
|
|
509
|
+
for (const child of el.children ?? []) {
|
|
510
|
+
if (child?.type !== "JSXElement") continue;
|
|
511
|
+
const sub = describeTree(child);
|
|
512
|
+
if (sub) children.push(sub);
|
|
513
|
+
}
|
|
514
|
+
if (tag[0] === tag[0]?.toUpperCase()) {
|
|
515
|
+
const node = { label: tag, children, ...where ? { at: where } : {} };
|
|
516
|
+
const id = components.get(el) ?? here.get(tag);
|
|
517
|
+
if (id !== void 0) node.owner = id;
|
|
518
|
+
else unresolved.push({ node, tag, file: file.path });
|
|
519
|
+
return node;
|
|
520
|
+
}
|
|
521
|
+
return { label: describeJsx(opening), children, ...where ? { at: where } : {} };
|
|
522
|
+
};
|
|
523
|
+
walk2(program, (node, stack) => {
|
|
524
|
+
if (node.type !== "JSXElement") return;
|
|
525
|
+
let owner;
|
|
526
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
527
|
+
const found = stack[i];
|
|
528
|
+
if (found.type === "JSXElement") return;
|
|
529
|
+
const id = components.get(found);
|
|
530
|
+
if (id !== void 0) {
|
|
531
|
+
owner = id;
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (owner === void 0) return;
|
|
536
|
+
const tree = describeTree(node);
|
|
537
|
+
if (!tree) return;
|
|
538
|
+
const held = domFor.get(owner);
|
|
539
|
+
if (held) held.push(tree);
|
|
540
|
+
else domFor.set(owner, [tree]);
|
|
541
|
+
});
|
|
542
|
+
walk2(program, (node, stack) => {
|
|
543
|
+
if (node.type !== "TaggedTemplateExpression") return;
|
|
544
|
+
const tagName = node.tag?.name;
|
|
545
|
+
if (tagName !== "html" && tagName !== "svg") return;
|
|
546
|
+
const quasi = node.quasi;
|
|
547
|
+
const expressions = quasi?.expressions ?? [];
|
|
548
|
+
const positionAt2 = positionOf();
|
|
549
|
+
let children;
|
|
550
|
+
try {
|
|
551
|
+
children = parseTemplate(templatePieces(quasi), { svg: tagName === "svg" }).root.children;
|
|
552
|
+
} catch {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const holeExpr = (index) => index == null ? void 0 : expressions[index];
|
|
556
|
+
const readsOf = (index) => {
|
|
557
|
+
const expr = holeExpr(index);
|
|
558
|
+
return expr ? mentions(expr) : /* @__PURE__ */ new Set();
|
|
559
|
+
};
|
|
560
|
+
const addControl = (tag, offset, hole, owner2) => {
|
|
561
|
+
const at = offset !== void 0 ? positionAt2(offset) : holeExpr(hole)?.loc?.start ?? node.loc?.start;
|
|
562
|
+
if (!at) return void 0;
|
|
563
|
+
const id = seq++;
|
|
564
|
+
pending.push({
|
|
565
|
+
node: {
|
|
566
|
+
id,
|
|
567
|
+
label: tag,
|
|
568
|
+
kind: directiveKind(tag),
|
|
569
|
+
deps: [],
|
|
570
|
+
writes: [],
|
|
571
|
+
runs: 0,
|
|
572
|
+
lastPulse: 0,
|
|
573
|
+
source: { file: file.path, line: at.line, column: at.column },
|
|
574
|
+
...owner2 !== void 0 ? { createdIn: owner2 } : {}
|
|
575
|
+
},
|
|
576
|
+
reads: readsOf(hole),
|
|
577
|
+
file: file.path
|
|
578
|
+
});
|
|
579
|
+
return id;
|
|
580
|
+
};
|
|
581
|
+
const addTarget = (index, element, attribute) => {
|
|
582
|
+
const expr = holeExpr(index);
|
|
583
|
+
const at = expr?.loc?.start;
|
|
584
|
+
if (!expr || !at) return;
|
|
585
|
+
const target = {
|
|
586
|
+
kind: attribute ? "attribute" : "content",
|
|
587
|
+
...attribute ? { name: attribute } : {},
|
|
588
|
+
element,
|
|
589
|
+
source: { file: file.path, line: at.line, column: at.column }
|
|
590
|
+
};
|
|
591
|
+
for (const name of mentions(expr)) holes.push({ file: file.path, name, target });
|
|
592
|
+
};
|
|
593
|
+
const elementTargets = (el) => {
|
|
594
|
+
const element = describeTemplateElement(el);
|
|
595
|
+
for (const attr of el.attributes) {
|
|
596
|
+
switch (attr.kind) {
|
|
597
|
+
case "Attribute":
|
|
598
|
+
for (const hole of valueHoles(attr.value)) addTarget(hole, element, attr.name);
|
|
599
|
+
break;
|
|
600
|
+
case "PropertyBinding":
|
|
601
|
+
case "BindDirective":
|
|
602
|
+
addTarget(attr.hole, element, attr.name);
|
|
603
|
+
break;
|
|
604
|
+
case "ClassDirective":
|
|
605
|
+
addTarget(attr.hole, element, "class");
|
|
606
|
+
break;
|
|
607
|
+
case "StyleDirective":
|
|
608
|
+
addTarget(attr.hole, element, "style");
|
|
609
|
+
break;
|
|
610
|
+
// A handler is not a read, and neither is a ref, a spread or a use.
|
|
611
|
+
default:
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
const visit = (nodes, owner2, holder) => {
|
|
617
|
+
for (const child of nodes) {
|
|
618
|
+
switch (child.kind) {
|
|
619
|
+
case "Element": {
|
|
620
|
+
const ifDir = child.attributes.find((a) => a.kind === "IfDirective");
|
|
621
|
+
const eachDir = child.attributes.find((a) => a.kind === "EachDirective");
|
|
622
|
+
let inner = owner2;
|
|
623
|
+
if (ifDir?.kind === "IfDirective") inner = addControl("Show", child.loc?.start, ifDir.hole, owner2) ?? owner2;
|
|
624
|
+
else if (eachDir?.kind === "EachDirective") inner = addControl("For", child.loc?.start, eachDir.hole, owner2) ?? owner2;
|
|
625
|
+
elementTargets(child);
|
|
626
|
+
visit(child.children, inner, describeTemplateElement(child));
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
case "Component": {
|
|
630
|
+
const tag = child.tag;
|
|
631
|
+
const own = here.has(tag) || from.has(tag);
|
|
632
|
+
if (tag && !own && DIRECTIVES.has(tag)) {
|
|
633
|
+
const prop = TRACKED_PROP[tag];
|
|
634
|
+
const tracked = prop ? child.attributes.find(
|
|
635
|
+
(a) => "name" in a && a.name === prop
|
|
636
|
+
) : void 0;
|
|
637
|
+
const hole = tracked && "hole" in tracked ? tracked.hole : tracked && "value" in tracked ? valueHoles(tracked.value)[0] : void 0;
|
|
638
|
+
const id = addControl(tag, child.loc?.start, hole, owner2);
|
|
639
|
+
visit(child.children, id ?? owner2, holder);
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
if (tag && owner2 !== void 0) usages.push({ tag, file: file.path, owner: owner2 });
|
|
643
|
+
visit(child.children, owner2, holder);
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
case "Fragment":
|
|
647
|
+
visit(child.children, owner2, holder);
|
|
648
|
+
break;
|
|
649
|
+
case "Expression":
|
|
650
|
+
addTarget(child.hole, holder, void 0);
|
|
651
|
+
break;
|
|
652
|
+
default:
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
let owner;
|
|
658
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
659
|
+
const found = components.get(stack[i]);
|
|
660
|
+
if (found !== void 0) {
|
|
661
|
+
owner = found;
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
visit(children, owner, "template");
|
|
666
|
+
});
|
|
667
|
+
walk2(program, (node, stack) => {
|
|
668
|
+
if (node.type !== "ObjectProperty" || node.computed) return;
|
|
669
|
+
const key = node.key?.name ?? node.key?.value;
|
|
670
|
+
if (key !== "component" && key !== "Component") return;
|
|
671
|
+
const value = node.value;
|
|
672
|
+
if (value?.type !== "Identifier") return;
|
|
673
|
+
const holder = [...stack].reverse().find((n) => n.type === "VariableDeclarator");
|
|
674
|
+
const via = holder?.id?.name;
|
|
675
|
+
if (via) routeRefs.push({ via, tag: value.name, file: file.path });
|
|
676
|
+
});
|
|
677
|
+
walk2(program, (node) => {
|
|
678
|
+
if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") return;
|
|
679
|
+
for (const name of here.keys()) sold.set(name, here.get(name));
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
const resolve = (file, name) => {
|
|
683
|
+
const local = locals.get(file)?.get(name);
|
|
684
|
+
if (local !== void 0) return local;
|
|
685
|
+
const source = imports.get(file)?.get(name);
|
|
686
|
+
if (!source) return void 0;
|
|
687
|
+
for (const [path, names] of exported) {
|
|
688
|
+
if (!sameModule(file, source, path)) continue;
|
|
689
|
+
const id = names.get(name);
|
|
690
|
+
if (id !== void 0) return id;
|
|
691
|
+
}
|
|
692
|
+
return void 0;
|
|
693
|
+
};
|
|
694
|
+
for (const entry of pending) {
|
|
695
|
+
const deps = /* @__PURE__ */ new Set();
|
|
696
|
+
for (const name of entry.reads) {
|
|
697
|
+
const id = resolve(entry.file, name);
|
|
698
|
+
if (id !== void 0 && id !== entry.node.id) deps.add(id);
|
|
699
|
+
}
|
|
700
|
+
entry.node.deps = [...deps];
|
|
701
|
+
}
|
|
702
|
+
const unique = /* @__PURE__ */ new Map();
|
|
703
|
+
for (const names of exported.values()) {
|
|
704
|
+
for (const [name, id] of names) unique.set(name, unique.has(name) ? null : id);
|
|
705
|
+
}
|
|
706
|
+
const byId = new Map(pending.map((p) => [p.node.id, p.node]));
|
|
707
|
+
for (const entry of unresolved) {
|
|
708
|
+
const id = resolve(entry.file, entry.tag) ?? unique.get(entry.tag) ?? void 0;
|
|
709
|
+
if (id !== void 0 && byId.get(id)?.kind === "component") entry.node.owner = id;
|
|
710
|
+
}
|
|
711
|
+
for (const [id, dom] of domFor) {
|
|
712
|
+
const node = byId.get(id);
|
|
713
|
+
if (node && dom.length) node.dom = dom;
|
|
714
|
+
}
|
|
715
|
+
for (const hole of holes) {
|
|
716
|
+
const id = resolve(hole.file, hole.name);
|
|
717
|
+
const node = id !== void 0 ? byId.get(id) : void 0;
|
|
718
|
+
if (!node || node.kind === "component") continue;
|
|
719
|
+
(node.targets ??= []).push(hole.target);
|
|
720
|
+
}
|
|
721
|
+
for (const ref of routeRefs) {
|
|
722
|
+
const named = resolve(ref.file, ref.tag) ?? unique.get(ref.tag) ?? void 0;
|
|
723
|
+
if (named === void 0) continue;
|
|
724
|
+
const router = pending.find(
|
|
725
|
+
(p) => p.file === ref.file && p.node.kind === "router" && p.node.id !== named && p.reads.has(ref.via)
|
|
726
|
+
)?.node.id;
|
|
727
|
+
const mentions2 = pending.find(
|
|
728
|
+
(p) => p.file === ref.file && (p.node.kind === "component" || p.node.kind === "handler") && p.node.id !== named && componentMentions.get(p.node.id)?.has(ref.via)
|
|
729
|
+
)?.node.id;
|
|
730
|
+
const holder = router ?? mentions2;
|
|
731
|
+
const node = byId.get(named);
|
|
732
|
+
if (node && node.createdIn === void 0 && holder !== void 0) node.createdIn = holder;
|
|
733
|
+
}
|
|
734
|
+
for (const use of usages) {
|
|
735
|
+
const id = resolve(use.file, use.tag) ?? unique.get(use.tag) ?? void 0;
|
|
736
|
+
if (id === void 0 || id === use.owner) continue;
|
|
737
|
+
const node = byId.get(id);
|
|
738
|
+
if (node && node.kind === "component" && node.createdIn === void 0) node.createdIn = use.owner;
|
|
739
|
+
}
|
|
740
|
+
const only = (kind, label) => {
|
|
741
|
+
const found = pending.filter((p) => p.node.kind === kind && p.node.label === label);
|
|
742
|
+
return found.length === 1 ? found[0].node.id : void 0;
|
|
743
|
+
};
|
|
744
|
+
const routeOwner = only("router", "Outlet") ?? only("router", "Router");
|
|
745
|
+
if (routeOwner !== void 0) {
|
|
746
|
+
for (const id of fileRoutes) {
|
|
747
|
+
const node = byId.get(id);
|
|
748
|
+
if (node && node.kind === "component" && node.createdIn === void 0 && id !== routeOwner) {
|
|
749
|
+
node.createdIn = routeOwner;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
const loose = pending.filter(
|
|
754
|
+
(p) => p.node.kind === "handler" && p.node.createdIn === void 0
|
|
755
|
+
);
|
|
756
|
+
if (loose.length > 0) {
|
|
757
|
+
const id = seq++;
|
|
758
|
+
pending.push({
|
|
759
|
+
node: {
|
|
760
|
+
id,
|
|
761
|
+
label: "api",
|
|
762
|
+
kind: "handler",
|
|
763
|
+
deps: [],
|
|
764
|
+
writes: [],
|
|
765
|
+
runs: 0,
|
|
766
|
+
lastPulse: 0,
|
|
767
|
+
// The directory, since there is no line of anyone's source to point at.
|
|
768
|
+
source: { file: apiDir, line: 1, column: 0 }
|
|
769
|
+
},
|
|
770
|
+
reads: /* @__PURE__ */ new Set(),
|
|
771
|
+
file: apiDir
|
|
772
|
+
});
|
|
773
|
+
for (const p of loose) p.node.createdIn = id;
|
|
774
|
+
}
|
|
775
|
+
return { t: Date.now(), nodes: pending.map((p) => p.node), static: true };
|
|
776
|
+
}
|
|
777
|
+
var withoutExtension = (path) => path.replace(/\.(tsx?|jsx?|mts|cts|mjs|cjs)$/, "");
|
|
778
|
+
function sameModule(importer, specifier, candidate) {
|
|
779
|
+
const base = importer.includes("/") ? importer.slice(0, importer.lastIndexOf("/")) : "";
|
|
780
|
+
const parts = (base ? base.split("/") : []).concat(specifier.split("/"));
|
|
781
|
+
const stack = [];
|
|
782
|
+
for (const part of parts) {
|
|
783
|
+
if (part === "." || part === "") continue;
|
|
784
|
+
if (part === "..") stack.pop();
|
|
785
|
+
else stack.push(part);
|
|
786
|
+
}
|
|
787
|
+
const resolved = withoutExtension(stack.join("/"));
|
|
788
|
+
const target = withoutExtension(candidate);
|
|
789
|
+
return target === resolved || target === `${resolved}/index`;
|
|
790
|
+
}
|
|
791
|
+
export {
|
|
792
|
+
analyzeReactiveGraph
|
|
793
|
+
};
|