@fluixi/compiler 1.0.0-alpha.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/babel-OGRQKOZA.mjs +2 -0
- package/dist/chunk-3SAEGOMQ.mjs +1 -0
- package/dist/codegen/backend.cjs +1 -0
- package/dist/codegen/backend.d.ts +22 -0
- package/dist/codegen/backend.d.ts.map +1 -0
- package/dist/codegen/backend.js +1 -0
- package/dist/codegen/backend.mjs +0 -0
- package/dist/codegen/backends/imperative.cjs +1 -0
- package/dist/codegen/backends/imperative.d.ts +3 -0
- package/dist/codegen/backends/imperative.d.ts.map +1 -0
- package/dist/codegen/backends/imperative.js +152 -0
- package/dist/codegen/backends/imperative.mjs +1 -0
- package/dist/codegen/contract.cjs +1 -0
- package/dist/codegen/contract.d.ts +25 -0
- package/dist/codegen/contract.d.ts.map +1 -0
- package/dist/codegen/contract.js +30 -0
- package/dist/codegen/contract.mjs +1 -0
- package/dist/frontend/babel/build-ir.cjs +1 -0
- package/dist/frontend/babel/build-ir.d.ts +23 -0
- package/dist/frontend/babel/build-ir.d.ts.map +1 -0
- package/dist/frontend/babel/build-ir.js +224 -0
- package/dist/frontend/babel/build-ir.mjs +1 -0
- package/dist/frontend/babel/index.cjs +2 -0
- package/dist/frontend/babel/index.d.ts +34 -0
- package/dist/frontend/babel/index.d.ts.map +1 -0
- package/dist/frontend/babel/index.js +65 -0
- package/dist/frontend/babel/index.mjs +2 -0
- package/dist/frontend/babel/plugin.cjs +2 -0
- package/dist/frontend/babel/plugin.d.ts +122 -0
- package/dist/frontend/babel/plugin.d.ts.map +1 -0
- package/dist/frontend/babel/plugin.js +1509 -0
- package/dist/frontend/babel/plugin.mjs +2 -0
- package/dist/frontend/babel/server-functions.cjs +1 -0
- package/dist/frontend/babel/server-functions.d.ts +11 -0
- package/dist/frontend/babel/server-functions.d.ts.map +1 -0
- package/dist/frontend/babel/server-functions.js +88 -0
- package/dist/frontend/babel/server-functions.mjs +1 -0
- package/dist/frontend/babel/types.cjs +1 -0
- package/dist/frontend/babel/types.d.ts +34 -0
- package/dist/frontend/babel/types.d.ts.map +1 -0
- package/dist/frontend/babel/types.js +1 -0
- package/dist/frontend/babel/types.mjs +0 -0
- package/dist/frontend/types.cjs +1 -0
- package/dist/frontend/types.d.ts +26 -0
- package/dist/frontend/types.d.ts.map +1 -0
- package/dist/frontend/types.js +1 -0
- package/dist/frontend/types.mjs +0 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.mjs +1 -0
- package/dist/integrations.cjs +12 -0
- package/dist/integrations.d.ts +251 -0
- package/dist/integrations.d.ts.map +1 -0
- package/dist/integrations.js +790 -0
- package/dist/integrations.mjs +11 -0
- package/dist/ir/nodes.cjs +1 -0
- package/dist/ir/nodes.d.ts +80 -0
- package/dist/ir/nodes.d.ts.map +1 -0
- package/dist/ir/nodes.js +1 -0
- package/dist/ir/nodes.mjs +0 -0
- package/dist/options.cjs +1 -0
- package/dist/options.d.ts +18 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +9 -0
- package/dist/options.mjs +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fluixi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/fluixi/assets/main/logos/128x128.png" alt="Fluixi" width="120" height="120" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @fluixi/compiler
|
|
6
|
+
|
|
7
|
+
**The Fluixi JSX compiler — host-agnostic IR + pluggable codegen backends.**
|
|
8
|
+
|
|
9
|
+
[](./LICENSE)
|
|
10
|
+

|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## ✨ Overview
|
|
16
|
+
|
|
17
|
+
`@fluixi/compiler` turns Fluixi JSX into fine-grained reactive output. A **Babel
|
|
18
|
+
front-end** parses source into a host-agnostic IR; a **codegen backend** emits the result:
|
|
19
|
+
|
|
20
|
+
- **`imperative`** (default) — compiles straight into [`@fluixi/dom`](../dom) runtime
|
|
21
|
+
calls (`createNativeElement`/`spread`/`insert`/`createComponent`/…). No VDOM.
|
|
22
|
+
- **`jsx`** — emits the automatic runtime `jsx()`/`jsxs()` (the [`@fluixi/jsx`](../jsx)
|
|
23
|
+
runtime).
|
|
24
|
+
|
|
25
|
+
It also provides the **`"use server"`** transform (server functions): the client build
|
|
26
|
+
gets an RPC stub, the server build keeps and registers the body.
|
|
27
|
+
|
|
28
|
+
Most apps don't use this package directly — [`@fluixi/vite-plugin`](../vite-plugin) (and
|
|
29
|
+
[`@fluixi/start`](../start)) wrap it.
|
|
30
|
+
|
|
31
|
+
## 📦 Installation
|
|
32
|
+
|
|
33
|
+
```ini
|
|
34
|
+
# .npmrc
|
|
35
|
+
@fluixi:registry=https://npm.pkg.github.com
|
|
36
|
+
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
pnpm add -D @fluixi/compiler
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 🚀 Usage
|
|
44
|
+
|
|
45
|
+
Via the Vite integration (the common path):
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { defineConfig } from 'vite';
|
|
49
|
+
import { createVitePlugin, serverFunctionsVitePlugin } from '@fluixi/compiler/integrations';
|
|
50
|
+
|
|
51
|
+
export default defineConfig({
|
|
52
|
+
plugins: [
|
|
53
|
+
serverFunctionsVitePlugin(), // "use server" transform
|
|
54
|
+
createVitePlugin({ backend: 'imperative' }),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or transform a string directly:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { transform } from '@fluixi/compiler';
|
|
63
|
+
const { code } = transform(source, { backend: 'imperative' });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 🔌 Subpaths
|
|
67
|
+
|
|
68
|
+
| Import | What |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `@fluixi/compiler` | `transform()` + the compile pipeline |
|
|
71
|
+
| `@fluixi/compiler/integrations` | `createVitePlugin`, `serverFunctionsVitePlugin`, webpack/rollup/esbuild adapters |
|
|
72
|
+
| `@fluixi/compiler/babel` | the Babel plugin front-end |
|
|
73
|
+
|
|
74
|
+
## 📄 License
|
|
75
|
+
|
|
76
|
+
[MIT](./LICENSE) © [Fluixi](https://fluixi.dev)
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./chunk-3SAEGOMQ.mjs";import{declare as Ae}from"@babel/helper-plugin-utils";import{types as e,template as Re}from"@babel/core";import{types as u,traverse as Je,template as Ce}from"@babel/core";import Y from"@babel/generator";var B={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},tt={version:2,module:"@fluixi/dom",symbols:[...B.symbols,"template","cloneTemplate","walk"]};var xe={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function Se(t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)}function K(t){return Se(t)?t:JSON.stringify(t)}function he(t){return t.expr!==void 0?t.reactive?`() => (${t.expr})`:`(${t.expr})`:JSON.stringify(t.literal??!0)}function be(t){return t.expr!==void 0?`(${t.expr})`:JSON.stringify(t.literal??!0)}function ye(t,n,r){let i=t.filter(l=>l.kind==="spread"),o=t.filter(l=>l.kind!=="spread").map(l=>`${K(l.name)}: ${he(l)}`);n!=null&&o.push(`children: ${n}`);let a=`{ ${o.join(", ")} }`;return i.length>0?(r.add("mergeProps"),`mergeProps(${i.map(l=>l.expr).join(", ")}, ${a})`):a}function Q(t,n){return t.length===1?$(t[0],n):`[${t.map(r=>$(r,n)).join(", ")}]`}function U(t,n,r,i){i.add("createMemo"),i.add("createComponent");let s=n.filter(p=>p.kind==="spread"),a=n.filter(p=>p.kind!=="spread").map(p=>`get ${K(p.name)}() { return ${be(p)}; }`);r.length>0&&a.push(`get children() { return ${Q(r,i)}; }`);let l=`{ ${a.join(", ")} }`;return s.length>0&&(i.add("mergeProps"),l=`mergeProps(${s.map(p=>p.expr).join(", ")}, ${l})`),`createMemo(() => createComponent(${t}, ${l}))`}function $(t,n){switch(t.kind){case"text":return JSON.stringify(t.value);case"expr":return t.reactive?`() => (${t.code})`:`(${t.code})`;case"fragment":return t.children.length===0?"null":Q(t.children,n);case"component":return U(t.name,t.props,t.children,n);case"control":{let r=xe[t.control]??t.control;return n.add(r),U(r,t.props,t.children,n)}case"element":{n.add("createNativeElement");let r=JSON.stringify(t.tag),i="_el$",s=[],o=t.svg?`${r}, true`:r;if(s.push(`const ${i} = createNativeElement(${o});`),t.props.length>0){n.add("spread");let a=t.svg?", isSVG: true":"";s.push(`spread({ element: ${i}, props: ${ye(t.props,null,n)}${a} });`)}for(let a of t.children){n.add("insert");let l=$(a,n),p=a.kind==="expr"&&a.reactive||a.kind==="component"||a.kind==="control";s.push(p?`insert(${i}, ${l}, null);`:`insert(${i}, ${l});`)}return s.push(`return ${i};`),`(() => { ${s.join(" ")} })()`}}}var D={name:"imperative",contract:B,emit(t,n){let r=new Set;return{code:$(t,r),imports:Array.from(r)}}};var Xe=Y.default??Y;function te(t){return Xe(t,{concise:!0}).code}function ve(t,n){let r=u.cloneNode(t,!0),i=u.file(u.program([u.expressionStatement(r)])),s=!1;return Je(i,{"JSXElement|JSXFragment"(o){let a=o.node,{code:l,imports:p}=D.emit(A(a,n),{});for(let b of p)n.add(b);let g=Ce.expression(l,{placeholderPattern:!1})();o.replaceWith(g),o.skip(),s=!0}}),s?i.program.body[0].expression:t}function V(t,n){return te(ve(t,n))}var we=new Set(["svg","path","circle","rect","line","polygon","polyline","ellipse","g","defs","clipPath","text"]),Fe=/^on[A-Z]/,je=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function Pe(t){if(u.isJSXIdentifier(t)){let n=t.name[0]!==t.name[0].toLowerCase();return{tag:t.name,component:n}}return u.isJSXMemberExpression(t)?{tag:te(t),component:!0}:u.isJSXNamespacedName(t)?{tag:`${t.namespace.name}:${t.name.name}`,component:!1}:{tag:"div",component:!1}}function Ie(t){return u.isJSXIdentifier(t)?t.name==="class"?"className":t.name:u.isJSXNamespacedName(t)?`${t.namespace.name}:${t.name.name}`:"unknown"}function F(t){return u.isCallExpression(t)||u.isOptionalCallExpression(t)?!0:u.isMemberExpression(t)||u.isOptionalMemberExpression(t)?!(!t.computed&&u.isIdentifier(t.property,{name:"children"})):u.isConditionalExpression(t)?F(t.test)||F(t.consequent)||F(t.alternate):u.isLogicalExpression(t)||u.isBinaryExpression(t)?F(t.left)||F(t.right):u.isTemplateLiteral(t)?t.expressions.some(n=>F(n)):!1}function Le(t,n){let r=Ie(t.name),i=Fe.test(r),o={name:r,kind:i?"event":"attr"};i&&(o.event={name:r.slice(2).toLowerCase(),delegated:je.has(r.slice(2).toLowerCase())});let a=t.value;if(a==null)return o.literal=!0,o;if(u.isStringLiteral(a))return o.literal=a.value,o;if(u.isJSXExpressionContainer(a)&&!u.isJSXEmptyExpression(a.expression)){let l=a.expression;return u.isStringLiteral(l)||u.isNumericLiteral(l)||u.isBooleanLiteral(l)?(o.literal=l.value,o):(o.expr=V(l,n),o.reactive=i?!1:F(l),(u.isJSXElement(l)||u.isJSXFragment(l))&&(o.jsxElement=!0),o)}return o.literal=!0,o}function Me(t,n){let r=[];for(let i of t)u.isJSXSpreadAttribute(i)?r.push({name:"",kind:"spread",expr:V(i.argument,n)}):u.isJSXAttribute(i)&&r.push(Le(i,n));return r}function Ne(t){let n=t.split(/\r\n|\n|\r/),r=0;for(let s=0;s<n.length;s++)/[^ \t]/.test(n[s])&&(r=s);let i="";for(let s=0;s<n.length;s++){let o=n[s].replace(/\t/g," ");s!==0&&(o=o.replace(/^ +/,"")),s!==n.length-1&&(o=o.replace(/ +$/,"")),o&&(s!==r&&(o+=" "),i+=o)}return i}function ee(t,n){let r=[];for(let i of t)if(u.isJSXText(i)){let s=Ne(i.value);s&&r.push({kind:"text",value:s})}else if(u.isJSXExpressionContainer(i)){if(!u.isJSXEmptyExpression(i.expression)){let s=i.expression;r.push({kind:"expr",code:V(s,n),reactive:F(s)})}}else u.isJSXElement(i)||u.isJSXFragment(i)?r.push(A(i,n)):u.isJSXSpreadChild(i)&&r.push({kind:"expr",code:V(i.expression,n),reactive:!1});return r}function A(t,n=new Set){if(u.isJSXFragment(t))return{kind:"fragment",children:ee(t.children,n)};let{tag:r,component:i}=Pe(t.openingElement.name),s=Me(t.openingElement.attributes,n),o=ee(t.children,n);return i?{kind:"component",name:r,props:s,children:o}:{kind:"element",tag:r,svg:we.has(r),props:s,children:o,static:!1}}var se=new Set(["Show","For","Index","Switch","Match","Portal","Dynamic","ErrorBoundary","Suspense"]),Oe={Show:"when",For:"each",Index:"each",Match:"when"};var oe=/^on[A-Z]/,ae=["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup","mouseover","mouseout","mouseenter","mouseleave"],O=Ae((t,n={})=>{t.assertVersion(7);let{runtime:r="automatic",importSource:i="@fluixi/jsx",pragma:s="jsx",pragmaFrag:o="Fragment",development:a=!1,detectReactivity:l=!0,useLitHTML:p=!0,hoistStatics:g=!0,delegateEvents:b=!0,delegatedEvents:m=ae,optimizeControlFlow:y=!0,sourceMaps:P=!0,signalModule:J="@fluixi/dom",controlFlowModule:w="@fluixi/dom",reactiveModule:L="@fluixi/reactive/signal",autoShowTransform:Z=!1,backend:X="imperative",codegen:M="inline"}=n,Ee={backend:X,codegen:M,irImports:new Set,libModule:"@fluixi/core",hasJSX:!1,hasReactivity:!1,hasLitHTML:!1,needsSignalImport:!1,needsControlFlowImport:!1,needsCreateMemo:!1,controlFlowComponents:new Set,delegatedEvents:new Set,staticElements:new Map,staticCounter:0};return{name:"@fluixi/babel-plugin-jsx",manipulateOptions(f,c){c.plugins.push("jsx","typescript")},pre(f){Object.assign(f,Ee)},visitor:{ImportDeclaration(f,c){f.node.source.value==="@fluixi/core/rx"&&(f.node.source=e.stringLiteral("@fluixi/reactive"))},Program:{enter(f,c){Object.assign(c,{hasJSX:!1,hasReactivity:!1,hasLitHTML:!1,needsSignalImport:!1,needsLitrxImport:!1,needsControlFlowImport:!1,needsCreateMemo:!1,controlFlowComponents:new Set,delegatedEvents:new Set,staticElements:new Map,autoShow:Z,staticCounter:0,libModule:"@fluixi/core",backend:X,codegen:M,irImports:new Set,needsCreateNativeElement:!1,needsInsert:!1,needsSpread:!1,needsCreateComponent:!1,needsMergeProps:!1})},exit(f,c){let d=[];if(c.hasJSX||(c.needsSignalImport&&d.push(e.importDeclaration([e.importSpecifier(e.identifier("signal"),e.identifier("signal"))],e.stringLiteral(J))),c.needsLitrxImport&&!f.scope.hasBinding("litrx")&&d.push(e.importDeclaration([e.importSpecifier(e.identifier("litrx"),e.identifier("litrx"))],e.stringLiteral(c.libModule)))),c.hasJSX){if(X==="imperative"&&M==="ir"){let x=new Set(["Show","For","Index","Switch","Match","Dynamic","ErrorBoundary","Portal","Suspense"]),S=new Set(["createMemo","createEffect","createRenderEffect","createRoot","createSignal","onCleanup","batch","untrack"]),E=Array.from(c.irImports),v=h=>e.importSpecifier(e.identifier(h),e.identifier(h)),I=h=>!f.scope.hasBinding(h),z=E.filter(h=>S.has(h)&&I(h)),T=E.filter(h=>!x.has(h)&&!S.has(h)&&I(h)),N=E.filter(h=>x.has(h)&&I(h));z.length>0&&d.push(e.importDeclaration(z.map(v),e.stringLiteral(L))),T.length>0&&d.push(e.importDeclaration(T.map(v),e.stringLiteral(J))),N.length>0&&d.push(e.importDeclaration(N.map(v),e.stringLiteral(w)))}else if(X==="imperative"){let S=[[!!c.needsCreateNativeElement,"createNativeElement"],[!!c.needsSpread,"spread"],[!!c.needsInsert,"insert"],[!!c.needsCreateComponent,"createComponent"],[!!c.needsMergeProps,"mergeProps"]].filter(([E,v])=>E&&!f.scope.hasBinding(v)).map(([,E])=>e.importSpecifier(e.identifier(E),e.identifier(E)));S.length>0&&d.push(e.importDeclaration(S,e.stringLiteral(J)))}else if(r==="automatic"){let x=[e.importSpecifier(e.identifier("jsx"),e.identifier("jsx")),e.importSpecifier(e.identifier("jsxs"),e.identifier("jsxs")),e.importSpecifier(e.identifier("Fragment"),e.identifier("Fragment"))];a&&x.push(e.importSpecifier(e.identifier("jsxDEV"),e.identifier("jsxDEV"))),c.needsMergeProps&&x.push(e.importSpecifier(e.identifier("mergeProps"),e.identifier("mergeProps"))),d.push(e.importDeclaration(x,e.stringLiteral(i)))}if(c.needsCreateMemo&&!f.scope.hasBinding("createMemo")&&d.push(e.importDeclaration([e.importSpecifier(e.identifier("createMemo"),e.identifier("createMemo"))],e.stringLiteral(X==="imperative"?L:c.libModule??"@fluixi/core"))),c.needsControlFlowImport&&c.controlFlowComponents.size>0){let x=Array.from(c.controlFlowComponents).filter(S=>!f.scope.hasBinding(S));if(x.length>0){let S=x.map(E=>e.importSpecifier(e.identifier(E),e.identifier(E)));d.push(e.importDeclaration(S,e.stringLiteral(w)))}}if(b&&c.delegatedEvents.size>0){d.push(e.importDeclaration([e.importSpecifier(e.identifier("delegateEvents"),e.identifier("delegateEvents"))],e.stringLiteral(X==="imperative"?J:"@fluixi/jsx")));let x=e.arrayExpression(Array.from(c.delegatedEvents).map(E=>e.stringLiteral(E))),S=e.expressionStatement(e.callExpression(e.identifier("delegateEvents"),[x]));f.node.body.unshift(S)}if(g&&c.staticElements.size>0){let x=[];c.staticElements.forEach((S,E)=>{x.push(e.variableDeclaration("const",[e.variableDeclarator(e.identifier(E),S)]))}),f.node.body.unshift(...x)}}d.length>0&&f.node.body.unshift(...d)}},JSXElement(f,c){if(c.hasJSX=!0,X==="imperative"&&M==="ir"){f.replaceWith(re(f.node,c));return}let d=f.node,x=d.openingElement;if(e.isJSXIdentifier(x.name)&&se.has(x.name.name)&&(c.controlFlowComponents.add(x.name.name),y)){let E=Qe(d,c);if(E){f.replaceWith(E);return}}if(g&&X!=="imperative"&&ge(d,c)){let E=Ke(d,c);if(E){f.replaceWith(E);return}}let S=ke(d,c,{runtime:r,pragma:s,development:a,detectReactivity:l,useLitHTML:p,autoShow:Z});f.replaceWith(S)},JSXFragment(f,c){if(c.hasJSX=!0,X==="imperative"&&M==="ir"){f.replaceWith(re(f.node,c));return}let d=_(f.node,c,{runtime:r,pragmaFrag:o,development:a});f.replaceWith(d)},CallExpression(f,c){if(!l)return;let d=f.node.callee;d.name,e.isIdentifier(d)&&(d.name==="createSignal"||d.name==="createStore"||d.name==="useContext"||d.name==="useLocation")&&(c.hasReactivity=!0)},JSXExpressionContainer(f){},TaggedTemplateExpression(f,c){let{tag:d,quasi:x}=f.node;f.get("quasi").get("expressions").forEach((S,E)=>{let v=S.node,I=x.quasis[E].value.raw;if(I.trim().endsWith("=")||I.match(/@[\w-]+$/))return;let T=!1,N=!1;if(e.isMemberExpression(v)){let h=v.property;e.isIdentifier(h)&&(h.name=h.name.replace("$",""),c.needsLitrxImport=!0,N=!0)}(T||N)&&S.replaceWith(e.callExpression(e.identifier("((window as any).Fluixi.litrx || litrx)"),[e.arrowFunctionExpression([],v)]))})}}}});function ke(t,n,r){let{runtime:i,pragma:s,development:o,autoShow:a=!0}=r;return i==="automatic"?k(t,n,o,a):Ve(t,n,s)}var Te=new Set(["svg","path","circle","rect","line","polygon","polyline","ellipse","g","defs","clipPath","text"]);function ne(t,n,r){return n.length>0?(r.needsMergeProps=!0,e.callExpression(e.identifier("mergeProps"),[...n,e.objectExpression(t)])):e.objectExpression(t)}function le(t){return t.length===1?t[0]:e.arrayExpression(t)}function $e(t,n,r,i,s,o){if(!n){let m=[...r];return s.length>0&&m.push(e.objectMethod("get",e.identifier("children"),[],e.blockStatement([e.returnStatement(le(s))]))),ce(t,ne(m,i,o),o)}let a=t.value,l=Te.has(a),p=e.identifier("_el$"),g=[];o.needsCreateNativeElement=!0;let b=[t];if(l&&b.push(e.booleanLiteral(!0)),g.push(e.variableDeclaration("const",[e.variableDeclarator(p,e.callExpression(e.identifier("createNativeElement"),b))])),r.length>0||i.length>0){o.needsSpread=!0;let m=[e.objectProperty(e.identifier("element"),p),e.objectProperty(e.identifier("props"),ne(r,i,o))];l&&m.push(e.objectProperty(e.identifier("isSVG"),e.booleanLiteral(!0))),g.push(e.expressionStatement(e.callExpression(e.identifier("spread"),[e.objectExpression(m)])))}if(s.length>0){o.needsInsert=!0;for(let m of s){let P=e.isArrowFunctionExpression(m)||e.isFunctionExpression(m)||e.isCallExpression(m)&&e.isIdentifier(m.callee)&&m.callee.name==="createMemo"?[e.cloneNode(p),m,e.nullLiteral()]:[e.cloneNode(p),m];g.push(e.expressionStatement(e.callExpression(e.identifier("insert"),P)))}}return g.push(e.returnStatement(p)),e.callExpression(e.arrowFunctionExpression([],e.blockStatement(g)),[])}function ce(t,n,r){return r.backend==="imperative"?(r.needsCreateComponent=!0,r.needsCreateMemo=!0,e.callExpression(e.identifier("createMemo"),[e.arrowFunctionExpression([],e.callExpression(e.identifier("createComponent"),[t,n]))])):e.callExpression(e.identifier("jsx"),[t,n])}function re(t,n){let r=new Set,i=A(t,r),{code:s,imports:o}=D.emit(i,{});for(let a of o)r.add(a);for(let a of r)n.irImports.add(a);return Re.expression(s,{placeholderPattern:!1})()}function De(t){return t.map(n=>{if(e.isObjectProperty(n)){let r=n.key,i=n.computed,s=n.value;return e.objectMethod("get",r,[],e.blockStatement([e.returnStatement(s)]),i)}return n})}function k(t,n,r,i=!0){let s=t.openingElement,o=t.children,a=pe(s.name),l=e.isJSXIdentifier(s.name)&&/^[a-z]/.test(s.name.name),p=fe(s.attributes,n,l,e.isJSXIdentifier(s.name)?s.name.name:""),g=p.props,b=p.spreads;l||(g=De(g));let m=q(o,n,i);if(n.backend==="imperative")return $e(a,l,g,b,m,n);if(m.length>0){let w=m.length===1?m[0]:e.arrayExpression(m);g.push(e.objectProperty(e.identifier("children"),w))}let y;if(b.length>0){let w=g.length>0?e.objectExpression(g):e.objectExpression([]);n.needsMergeProps=!0,y=e.callExpression(e.identifier("mergeProps"),[...b,w])}else y=e.objectExpression(g);let P=r?"jsxDEV":m.length>1?"jsxs":"jsx",J=[a,y];return r&&J.push(e.identifier("undefined"),e.booleanLiteral(!1),e.identifier("undefined"),e.identifier("undefined")),e.callExpression(e.identifier(P),J)}function Ve(t,n,r){let i=t.openingElement,s=t.children,o=pe(i.name),a=e.isJSXIdentifier(i.name)&&/^[a-z]/.test(i.name.name),{props:l,spreads:p}=fe(i.attributes,n,a,e.isJSXIdentifier(i.name)?i.name.name:""),g=q(s,n,n.autoShow??!0),b;if(p.length>0){let y=l.length>0?e.objectExpression(l):e.objectExpression([]);n.needsMergeProps=!0,b=e.callExpression(e.identifier("mergeProps"),[...p,y])}else b=l.length>0?e.objectExpression(l):e.nullLiteral();let m=[o,b,...g];return e.callExpression(e.identifier(r),m)}function _(t,n,r){let{runtime:i,pragmaFrag:s,development:o}=r,a=q(t.children,n,n.autoShow??!0);if(n.backend==="imperative")return a.length===0?e.nullLiteral():le(a);if(i==="automatic"){let l=o?"jsxDEV":a.length>1?"jsxs":"jsx",p=e.objectExpression([e.objectProperty(e.identifier("children"),a.length===1?a[0]:e.arrayExpression(a))]),g=[e.identifier("Fragment"),p];return o&&g.push(e.identifier("undefined"),e.booleanLiteral(!1),e.identifier("undefined"),e.identifier("undefined")),e.callExpression(e.identifier(l),g)}else return e.callExpression(e.identifier(s),a)}function pe(t){if(e.isJSXIdentifier(t)){let n=t.name;return n[0]===n[0].toLowerCase()?e.stringLiteral(n):e.identifier(n)}return e.isJSXMemberExpression(t)?ue(t):e.isJSXNamespacedName(t)?e.stringLiteral(`${t.namespace.name}:${t.name.name}`):e.stringLiteral("div")}function ue(t){let n;return e.isJSXIdentifier(t.object)?n=e.identifier(t.object.name):n=ue(t.object),e.memberExpression(n,e.identifier(t.property.name))}function _e(t){return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(t)}function fe(t,n,r=!0,i=""){let s=[],o=[],a=Oe[i];for(let l of t)if(e.isJSXSpreadAttribute(l))o.push(l.argument);else if(e.isJSXAttribute(l)){let p=ze(l.name),g=Be(l.value,n,p,r);if(oe.test(p)){let L=p.slice(2).toLowerCase();ae.includes(L)&&n.delegatedEvents.add(L)}let b=_e(p)?e.identifier(p):e.stringLiteral(p),m=l.value,y=e.isJSXElement(m)||e.isJSXFragment(m)||e.isJSXExpressionContainer(m)&&(e.isJSXElement(m.expression)||e.isJSXFragment(m.expression)),P=!r&&p===a,J=e.isJSXExpressionContainer(m)&&!e.isJSXEmptyExpression(m.expression)?m.expression:null,w=!r&&!!J&&me(J,p);!r&&y||P||w?s.push(e.objectMethod("get",b,[],e.blockStatement([e.returnStatement(g)]))):s.push(e.objectProperty(b,g))}return{props:s,spreads:o}}function ze(t){return e.isJSXIdentifier(t)?t.name==="class"?"className":t.name:e.isJSXNamespacedName(t)?`${t.namespace.name}:${t.name.name}`:"unknown"}function Be(t,n,r="",i=!0){if(t===null)return e.booleanLiteral(!0);if(e.isStringLiteral(t))return t.value.includes(`
|
|
2
|
+
`)?e.stringLiteral(t.value.replace(/\s+/g," ").trim()):t;if(e.isJSXExpressionContainer(t)){if(e.isJSXEmptyExpression(t.expression))return e.booleanLiteral(!0);let s=t.expression;return i&&me(s,r)?e.arrowFunctionExpression([],s):s}return e.isJSXElement(t)?k(t,n,!1,n.autoShow??!0):e.isJSXFragment(t)?_(t,n,{runtime:"automatic",pragmaFrag:"Fragment",development:!1}):e.booleanLiteral(!0)}function me(t,n){return oe.test(n)||n.startsWith("on:")||n==="ref"||n.startsWith("use:")||e.isArrowFunctionExpression(t)||e.isFunctionExpression(t)||e.isIdentifier(t)||e.isStringLiteral(t)||e.isNumericLiteral(t)||e.isBooleanLiteral(t)||e.isNullLiteral(t)?!1:!!(e.isCallExpression(t)||e.isOptionalCallExpression(t)||e.isMemberExpression(t)||e.isOptionalMemberExpression(t)||e.isLogicalExpression(t)||e.isConditionalExpression(t)||e.isBinaryExpression(t)||e.isUnaryExpression(t)||e.isTemplateLiteral(t)||e.isObjectExpression(t)||e.isArrayExpression(t))}function We(t){let n=t.split(/\r\n|\n|\r/),r=0;for(let s=0;s<n.length;s++)/[^ \t]/.test(n[s])&&(r=s);let i="";for(let s=0;s<n.length;s++){let o=n[s].replace(/\t/g," ");s!==0&&(o=o.replace(/^ +/,"")),s!==n.length-1&&(o=o.replace(/ +$/,"")),o&&(s!==r&&(o+=" "),i+=o)}return i}function q(t,n,r=!0){let i=[];for(let s of t)if(e.isJSXText(s)){let o=We(s.value);o&&i.push(e.stringLiteral(o))}else if(e.isJSXExpressionContainer(s)){if(!e.isJSXEmptyExpression(s.expression)){let o=s.expression;if(r){let a=qe(o,n)??Ge(o,n);if(a){i.push(a);continue}}else{let a=He(o,n);if(a){i.push(a);continue}}Ue(o)?i.push(e.arrowFunctionExpression([],o)):i.push(o)}}else e.isJSXElement(s)?i.push(k(s,n,!1,n.autoShow??!0)):e.isJSXFragment(s)?i.push(_(s,n,{runtime:"automatic",pragmaFrag:"Fragment",development:!1})):e.isJSXSpreadChild(s)&&i.push(s.expression);return i}function qe(t,n){if(!e.isArrowFunctionExpression(t)||t.params.length!==0||t.async)return null;let r=t.body;if(e.isLogicalExpression(r)&&r.operator==="&&"){let i=C(r.right);if(i)return R(j(r.left),i,null,n)}if(e.isConditionalExpression(r)){let i=C(r.consequent);if(i){let s=G(r.alternate,n);return R(j(r.test),i,s,n,!0)}}return null}function Ge(t,n){if(e.isLogicalExpression(t)&&t.operator==="&&"){let r=C(t.right);if(r)return R(j(t.left),r,null,n)}if(e.isConditionalExpression(t)){let r=C(t.consequent);if(r){let i=G(t.alternate,n);return R(j(t.test),r,i,n)}}return null}function He(t,n){let r=e.isArrowFunctionExpression(t)&&t.params.length===0&&!t.async&&e.isExpression(t.body)?t.body:t;if(e.isConditionalExpression(r)){let i=j(r.test),o=C(r.consequent)??r.consequent,l=C(r.alternate)??r.alternate,p=e.conditionalExpression(i,o,l);return W(r.consequent)||W(r.alternate)?null:(n.needsCreateMemo=!0,e.callExpression(e.identifier("createMemo"),[e.arrowFunctionExpression([],p)]))}if(e.isLogicalExpression(r)&&r.operator==="&&"){let i=j(r.left),o=C(r.right)??r.right,a=e.logicalExpression("&&",i,o);return W(r.right)?null:(n.needsCreateMemo=!0,e.callExpression(e.identifier("createMemo"),[e.arrowFunctionExpression([],a)]))}return null}function G(t,n){if(Ze(t))return null;let r=C(t);if(r)return de(r,n);if(e.isConditionalExpression(t)){let i=t,s=C(i.consequent);if(s){let o=G(i.alternate,n);return R(j(i.test),s,o,n)}}return t}function ie(t){return e.isJSXElement(t)||e.isJSXFragment(t)}function W(t){let n=C(t);if(!n||!e.isJSXElement(n))return!1;let r=n.openingElement.name;return e.isJSXIdentifier(r)&&se.has(r.name)}function C(t){return ie(t)?t:e.isArrowFunctionExpression(t)&&t.params.length===0&&!t.async&&ie(t.body)?t.body:null}function j(t){return e.isArrowFunctionExpression(t)&&t.params.length===0&&!t.async&&e.isExpression(t.body)?t.body:t}function Ze(t){return e.isNullLiteral(t)||e.isIdentifier(t)&&t.name==="undefined"||e.isBooleanLiteral(t)&&t.value===!1}function de(t,n){return e.isJSXElement(t)?k(t,n,!1,n.autoShow??!0):_(t,n,{runtime:"automatic",pragmaFrag:"Fragment",development:!1})}function R(t,n,r,i,s=!1){i.controlFlowComponents.add("Show"),i.needsControlFlowImport=!0;let o=de(n,i),a=[e.objectProperty(e.identifier("when"),e.arrowFunctionExpression([],t)),e.objectProperty(e.identifier("children"),o)];return r&&a.push(e.objectProperty(e.identifier("fallback"),r)),ce(e.identifier("Show"),e.objectExpression(a),i)}function Ue(t){return e.isMemberExpression(t)||e.isOptionalMemberExpression(t)?!(!t.computed&&e.isIdentifier(t.property,{name:"children"})):e.isCallExpression(t)||e.isOptionalCallExpression(t)?!0:e.isIdentifier(t)?!1:!!(e.isLogicalExpression(t)||e.isConditionalExpression(t)||e.isBinaryExpression(t)||e.isUnaryExpression(t)||e.isTemplateLiteral(t))}function ge(t,n){let r=t.openingElement;if(!e.isJSXIdentifier(r.name))return!1;let i=r.name.name;if(i[0]!==i[0].toLowerCase())return!1;for(let s of r.attributes){if(e.isJSXSpreadAttribute(s))return!1;if(e.isJSXAttribute(s)){let o=s.value;if(e.isJSXExpressionContainer(o)&&!e.isStringLiteral(o.expression)&&!e.isNumericLiteral(o.expression))return!1}}for(let s of t.children)if(e.isJSXElement(s)&&!ge(s,n)||e.isJSXExpressionContainer(s))return!1;return!0}function Ke(t,n){let r=`_$static${n.staticCounter++}`,i=k(t,n,!1);return n.staticElements.set(r,i),e.identifier(r)}function Qe(t,n){let r=t.openingElement.name.name;return r==="Show"?Ye(t,n):r==="For"?et(t,n):null}function Ye(t,n){return null}function et(t,n){return null}var Et=O;function xt(t){return[O,t]}function H(t={}){return{plugins:[[O,{runtime:"automatic",importSource:"@fluixi/jsx",development:!1,detectReactivity:!0,useLitHTML:!0,hoistStatics:!0,delegateEvents:!0,optimizeControlFlow:!0,sourceMaps:!0,...t}]]}}var St={production:H({development:!1,hoistStatics:!0,delegateEvents:!0,optimizeControlFlow:!0}),development:H({development:!0,hoistStatics:!1,sourceMaps:!0}),minimal:H({detectReactivity:!1,useLitHTML:!1,hoistStatics:!1,delegateEvents:!1,optimizeControlFlow:!1})};export{Et as babelPluginReactiveJSX,xt as createPlugin,H as createPreset,O as default,St as presets};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var d=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});export{d as a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var r=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var c=(o,t,i,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of m(t))!s.call(o,e)&&e!==i&&r(o,e,{get:()=>t[e],enumerable:!(n=p(t,e))||n.enumerable});return o};var a=o=>c(r({},"__esModule",{value:!0}),o);var d={};module.exports=a(d);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IRNode } from '../ir/nodes.js';
|
|
2
|
+
import type { RuntimeContract } from './contract.js';
|
|
3
|
+
import type { CompilerOptions } from '../options.js';
|
|
4
|
+
export interface CodegenResult {
|
|
5
|
+
code: string;
|
|
6
|
+
map?: unknown;
|
|
7
|
+
/** runtime symbols this output imports (subset of the backend's contract) */
|
|
8
|
+
imports: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A codegen backend turns IR into runtime calls. This is the swap point: the
|
|
12
|
+
* imperative backend ships now; a template-clone backend (and hybrids/islands
|
|
13
|
+
* variants) plug in later without touching the front-ends or IR.
|
|
14
|
+
*/
|
|
15
|
+
export interface CodegenBackend {
|
|
16
|
+
/** stable id used in CompilerOptions.backend */
|
|
17
|
+
name: string;
|
|
18
|
+
/** the runtime contract this backend emits against */
|
|
19
|
+
contract: RuntimeContract;
|
|
20
|
+
emit(node: IRNode, options: CompilerOptions): CodegenResult;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/codegen/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,6EAA6E;IAC7E,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,aAAa,CAAC;CAC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var l=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var C=(e,t)=>{for(var r in t)l(e,r,{get:t[r],enumerable:!0})},N=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $(t))!h.call(e,o)&&o!==r&&l(e,o,{get:()=>t[o],enumerable:!(n=f(t,o))||n.enumerable});return e};var R=e=>N(l({},"__esModule",{value:!0}),e);var O={};C(O,{imperativeBackend:()=>k});module.exports=R(O);var m={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},T={version:2,module:"@fluixi/dom",symbols:[...m.symbols,"template","cloneTemplate","walk"]};var y={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function x(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function g(e){return x(e)?e:JSON.stringify(e)}function v(e){return e.expr!==void 0?e.reactive?`() => (${e.expr})`:`(${e.expr})`:JSON.stringify(e.literal??!0)}function I(e){return e.expr!==void 0?`(${e.expr})`:JSON.stringify(e.literal??!0)}function S(e,t,r){let n=e.filter(i=>i.kind==="spread"),c=e.filter(i=>i.kind!=="spread").map(i=>`${g(i.name)}: ${v(i)}`);t!=null&&c.push(`children: ${t}`);let s=`{ ${c.join(", ")} }`;return n.length>0?(r.add("mergeProps"),`mergeProps(${n.map(i=>i.expr).join(", ")}, ${s})`):s}function d(e,t){return e.length===1?p(e[0],t):`[${e.map(r=>p(r,t)).join(", ")}]`}function u(e,t,r,n){n.add("createMemo"),n.add("createComponent");let o=t.filter(a=>a.kind==="spread"),s=t.filter(a=>a.kind!=="spread").map(a=>`get ${g(a.name)}() { return ${I(a)}; }`);r.length>0&&s.push(`get children() { return ${d(r,n)}; }`);let i=`{ ${s.join(", ")} }`;return o.length>0&&(n.add("mergeProps"),i=`mergeProps(${o.map(a=>a.expr).join(", ")}, ${i})`),`createMemo(() => createComponent(${e}, ${i}))`}function p(e,t){switch(e.kind){case"text":return JSON.stringify(e.value);case"expr":return e.reactive?`() => (${e.code})`:`(${e.code})`;case"fragment":return e.children.length===0?"null":d(e.children,t);case"component":return u(e.name,e.props,e.children,t);case"control":{let r=y[e.control]??e.control;return t.add(r),u(r,e.props,e.children,t)}case"element":{t.add("createNativeElement");let r=JSON.stringify(e.tag),n="_el$",o=[],c=e.svg?`${r}, true`:r;if(o.push(`const ${n} = createNativeElement(${c});`),e.props.length>0){t.add("spread");let s=e.svg?", isSVG: true":"";o.push(`spread({ element: ${n}, props: ${S(e.props,null,t)}${s} });`)}for(let s of e.children){t.add("insert");let i=p(s,t),a=s.kind==="expr"&&s.reactive||s.kind==="component"||s.kind==="control";o.push(a?`insert(${n}, ${i}, null);`:`insert(${n}, ${i});`)}return o.push(`return ${n};`),`(() => { ${o.join(" ")} })()`}}}var k={name:"imperative",contract:m,emit(e,t){let r=new Set;return{code:p(e,r),imports:Array.from(r)}}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imperative.d.ts","sourceRoot":"","sources":["../../../src/codegen/backends/imperative.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,eAAe,CAAC;AAkKnE,eAAO,MAAM,iBAAiB,EAAE,cAQ/B,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { RUNTIME_CONTRACT_V1 } from '../contract.js';
|
|
2
|
+
/**
|
|
3
|
+
* Imperative fine-grained backend — emits createNativeElement/insert/spread/
|
|
4
|
+
* createComponent (RUNTIME_CONTRACT_V1), the runtime proven by the @fluixi/dom
|
|
5
|
+
* contract tests.
|
|
6
|
+
*
|
|
7
|
+
* emit() consumes the host-agnostic IR and returns a code string, so any
|
|
8
|
+
* front-end (babel now, swc later) that can produce IR reuses this exact codegen.
|
|
9
|
+
* The output mirrors what the babel front-end emits inline today:
|
|
10
|
+
*
|
|
11
|
+
* element -> (() => { const _el$ = createNativeElement(tag);
|
|
12
|
+
* spread({ element: _el$, props });
|
|
13
|
+
* insert(_el$, children); return _el$; })()
|
|
14
|
+
* component -> createMemo(() => createComponent(Name, props))
|
|
15
|
+
* fragment -> [ ...children ]
|
|
16
|
+
*/
|
|
17
|
+
const CONTROL_COMPONENT = {
|
|
18
|
+
show: 'Show',
|
|
19
|
+
for: 'For',
|
|
20
|
+
index: 'Index',
|
|
21
|
+
switch: 'Switch',
|
|
22
|
+
match: 'Match',
|
|
23
|
+
dynamic: 'Dynamic',
|
|
24
|
+
errorBoundary: 'ErrorBoundary',
|
|
25
|
+
suspense: 'Suspense',
|
|
26
|
+
};
|
|
27
|
+
function isIdent(name) {
|
|
28
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
|
|
29
|
+
}
|
|
30
|
+
function propKey(name) {
|
|
31
|
+
return isIdent(name) ? name : JSON.stringify(name);
|
|
32
|
+
}
|
|
33
|
+
function propValue(p) {
|
|
34
|
+
if (p.expr !== undefined) {
|
|
35
|
+
// Events and non-reactive expressions pass through; reactive ones become thunks
|
|
36
|
+
// so the runtime (spread/insert) can wire a render effect.
|
|
37
|
+
return p.reactive ? `() => (${p.expr})` : `(${p.expr})`;
|
|
38
|
+
}
|
|
39
|
+
return JSON.stringify(p.literal ?? true);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Component props are passed as VALUES, not thunks (unlike native-element attrs).
|
|
43
|
+
* The whole `createComponent(...)` call sits inside a `createMemo`, so reading a
|
|
44
|
+
* signal in a prop re-evaluates when the memo re-runs — no per-prop thunk needed.
|
|
45
|
+
* This matches the inline codegen; wrapping a prop like
|
|
46
|
+
* `history={createMemoryHistory()}` in `() => …` would hand the component a
|
|
47
|
+
* function instead of the value (e.g. `history.get is not a function`).
|
|
48
|
+
*/
|
|
49
|
+
function componentPropValue(p) {
|
|
50
|
+
if (p.expr !== undefined)
|
|
51
|
+
return `(${p.expr})`;
|
|
52
|
+
return JSON.stringify(p.literal ?? true);
|
|
53
|
+
}
|
|
54
|
+
/** Build a props object literal (or mergeProps(...) when spreads are present). */
|
|
55
|
+
function emitProps(props, childrenExpr, used) {
|
|
56
|
+
const spreads = props.filter((p) => p.kind === 'spread');
|
|
57
|
+
const normal = props.filter((p) => p.kind !== 'spread');
|
|
58
|
+
const entries = normal.map((p) => `${propKey(p.name)}: ${propValue(p)}`);
|
|
59
|
+
if (childrenExpr != null)
|
|
60
|
+
entries.push(`children: ${childrenExpr}`);
|
|
61
|
+
const obj = `{ ${entries.join(', ')} }`;
|
|
62
|
+
if (spreads.length > 0) {
|
|
63
|
+
used.add('mergeProps');
|
|
64
|
+
return `mergeProps(${spreads.map((s) => s.expr).join(', ')}, ${obj})`;
|
|
65
|
+
}
|
|
66
|
+
return obj;
|
|
67
|
+
}
|
|
68
|
+
function emitChildren(children, used) {
|
|
69
|
+
if (children.length === 1)
|
|
70
|
+
return emitNode(children[0], used);
|
|
71
|
+
return `[${children.map((c) => emitNode(c, used)).join(', ')}]`;
|
|
72
|
+
}
|
|
73
|
+
function emitComponent(name, props, children, used) {
|
|
74
|
+
used.add('createMemo');
|
|
75
|
+
used.add('createComponent');
|
|
76
|
+
const spreads = props.filter((p) => p.kind === 'spread');
|
|
77
|
+
const normal = props.filter((p) => p.kind !== 'spread');
|
|
78
|
+
// ALL component props are emitted as getters (Solid model): reading a signal in a prop
|
|
79
|
+
// eagerly inside `createMemo(() => createComponent(...))` would re-create the whole component
|
|
80
|
+
// on every change (a <Portal> then piles up). As getters the component is built ONCE and
|
|
81
|
+
// reactivity flows through the getter into its own effects. Static props as getters are
|
|
82
|
+
// harmless (they return the same value). Matches lazyProps() in the inline codegen.
|
|
83
|
+
const entries = normal.map((p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`);
|
|
84
|
+
if (children.length > 0) {
|
|
85
|
+
// Children are a LAZY getter: evaluated inside the component's execution, so
|
|
86
|
+
// child components are created in the component's owner scope (preserves owner
|
|
87
|
+
// nesting for context/Suspense), after the component runs (correct provider
|
|
88
|
+
// ordering), and lazily (ErrorBoundary can still catch a throwing child).
|
|
89
|
+
entries.push(`get children() { return ${emitChildren(children, used)}; }`);
|
|
90
|
+
}
|
|
91
|
+
let obj = `{ ${entries.join(', ')} }`;
|
|
92
|
+
if (spreads.length > 0) {
|
|
93
|
+
used.add('mergeProps');
|
|
94
|
+
obj = `mergeProps(${spreads.map((s) => s.expr).join(', ')}, ${obj})`;
|
|
95
|
+
}
|
|
96
|
+
return `createMemo(() => createComponent(${name}, ${obj}))`;
|
|
97
|
+
}
|
|
98
|
+
function emitNode(node, used) {
|
|
99
|
+
switch (node.kind) {
|
|
100
|
+
case 'text':
|
|
101
|
+
return JSON.stringify(node.value);
|
|
102
|
+
case 'expr':
|
|
103
|
+
return node.reactive ? `() => (${node.code})` : `(${node.code})`;
|
|
104
|
+
case 'fragment':
|
|
105
|
+
if (node.children.length === 0)
|
|
106
|
+
return 'null';
|
|
107
|
+
return emitChildren(node.children, used);
|
|
108
|
+
case 'component':
|
|
109
|
+
return emitComponent(node.name, node.props, node.children, used);
|
|
110
|
+
case 'control': {
|
|
111
|
+
const name = CONTROL_COMPONENT[node.control] ?? node.control;
|
|
112
|
+
used.add(name);
|
|
113
|
+
return emitComponent(name, node.props, node.children, used);
|
|
114
|
+
}
|
|
115
|
+
case 'element': {
|
|
116
|
+
used.add('createNativeElement');
|
|
117
|
+
const tag = JSON.stringify(node.tag);
|
|
118
|
+
const el = '_el$';
|
|
119
|
+
const parts = [];
|
|
120
|
+
const createArgs = node.svg ? `${tag}, true` : tag;
|
|
121
|
+
parts.push(`const ${el} = createNativeElement(${createArgs});`);
|
|
122
|
+
if (node.props.length > 0) {
|
|
123
|
+
used.add('spread');
|
|
124
|
+
const svgFlag = node.svg ? ', isSVG: true' : '';
|
|
125
|
+
parts.push(`spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag} });`);
|
|
126
|
+
}
|
|
127
|
+
// Insert each child individually (like the jsx runtime's applyProps), so a
|
|
128
|
+
// reactive/component child that isn't the only child still gets its own
|
|
129
|
+
// reactive binding. A single insert(el, [array]) does NOT bind function
|
|
130
|
+
// elements sitting inside the array.
|
|
131
|
+
for (const child of node.children) {
|
|
132
|
+
used.add('insert');
|
|
133
|
+
const childCode = emitNode(child, used);
|
|
134
|
+
const isFn = (child.kind === 'expr' && child.reactive) ||
|
|
135
|
+
child.kind === 'component' ||
|
|
136
|
+
child.kind === 'control';
|
|
137
|
+
parts.push(isFn ? `insert(${el}, ${childCode}, null);` : `insert(${el}, ${childCode});`);
|
|
138
|
+
}
|
|
139
|
+
parts.push(`return ${el};`);
|
|
140
|
+
return `(() => { ${parts.join(' ')} })()`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export const imperativeBackend = {
|
|
145
|
+
name: 'imperative',
|
|
146
|
+
contract: RUNTIME_CONTRACT_V1,
|
|
147
|
+
emit(node, _options) {
|
|
148
|
+
const used = new Set();
|
|
149
|
+
const code = emitNode(node, used);
|
|
150
|
+
return { code, imports: Array.from(used) };
|
|
151
|
+
},
|
|
152
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var l={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},N={version:2,module:"@fluixi/dom",symbols:[...l.symbols,"template","cloneTemplate","walk"]};var d={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function f(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function u(e){return f(e)?e:JSON.stringify(e)}function $(e){return e.expr!==void 0?e.reactive?`() => (${e.expr})`:`(${e.expr})`:JSON.stringify(e.literal??!0)}function h(e){return e.expr!==void 0?`(${e.expr})`:JSON.stringify(e.literal??!0)}function C(e,t,r){let o=e.filter(n=>n.kind==="spread"),c=e.filter(n=>n.kind!=="spread").map(n=>`${u(n.name)}: ${$(n)}`);t!=null&&c.push(`children: ${t}`);let i=`{ ${c.join(", ")} }`;return o.length>0?(r.add("mergeProps"),`mergeProps(${o.map(n=>n.expr).join(", ")}, ${i})`):i}function g(e,t){return e.length===1?p(e[0],t):`[${e.map(r=>p(r,t)).join(", ")}]`}function m(e,t,r,o){o.add("createMemo"),o.add("createComponent");let a=t.filter(s=>s.kind==="spread"),i=t.filter(s=>s.kind!=="spread").map(s=>`get ${u(s.name)}() { return ${h(s)}; }`);r.length>0&&i.push(`get children() { return ${g(r,o)}; }`);let n=`{ ${i.join(", ")} }`;return a.length>0&&(o.add("mergeProps"),n=`mergeProps(${a.map(s=>s.expr).join(", ")}, ${n})`),`createMemo(() => createComponent(${e}, ${n}))`}function p(e,t){switch(e.kind){case"text":return JSON.stringify(e.value);case"expr":return e.reactive?`() => (${e.code})`:`(${e.code})`;case"fragment":return e.children.length===0?"null":g(e.children,t);case"component":return m(e.name,e.props,e.children,t);case"control":{let r=d[e.control]??e.control;return t.add(r),m(r,e.props,e.children,t)}case"element":{t.add("createNativeElement");let r=JSON.stringify(e.tag),o="_el$",a=[],c=e.svg?`${r}, true`:r;if(a.push(`const ${o} = createNativeElement(${c});`),e.props.length>0){t.add("spread");let i=e.svg?", isSVG: true":"";a.push(`spread({ element: ${o}, props: ${C(e.props,null,t)}${i} });`)}for(let i of e.children){t.add("insert");let n=p(i,t),s=i.kind==="expr"&&i.reactive||i.kind==="component"||i.kind==="control";a.push(s?`insert(${o}, ${n}, null);`:`insert(${o}, ${n});`)}return a.push(`return ${o};`),`(() => { ${a.join(" ")} })()`}}}var x={name:"imperative",contract:l,emit(e,t){let r=new Set;return{code:p(e,r),imports:Array.from(r)}}};export{x as imperativeBackend};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var r=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var c=(t,e)=>{for(var n in e)r(t,n,{get:e[n],enumerable:!0})},u=(t,e,n,m)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of i(e))!l.call(t,o)&&o!==n&&r(t,o,{get:()=>e[o],enumerable:!(m=a(e,o))||m.enumerable});return t};var d=t=>u(r({},"__esModule",{value:!0}),t);var p={};c(p,{RUNTIME_CONTRACT_V1:()=>s,RUNTIME_CONTRACT_V2:()=>C});module.exports=d(p);var s={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},C={version:2,module:"@fluixi/dom",symbols:[...s.symbols,"template","cloneTemplate","walk"]};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The RuntimeContract is the exact set of runtime symbols a codegen backend may
|
|
3
|
+
* emit, paired with the module they import from and a version number. Backend
|
|
4
|
+
* and runtime evolve in lockstep: adding a primitive bumps the version, so old
|
|
5
|
+
* and new backends/runtimes can coexist during a migration.
|
|
6
|
+
*/
|
|
7
|
+
export interface RuntimeContract {
|
|
8
|
+
version: number;
|
|
9
|
+
/** module the emitted symbols are imported from */
|
|
10
|
+
module: string;
|
|
11
|
+
symbols: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* v1 — the imperative fine-grained runtime, locked by the @fluixi/dom contract
|
|
15
|
+
* tests (createNativeElement/insert/spread/delegateEvents/createComponent + the
|
|
16
|
+
* control-flow components).
|
|
17
|
+
*/
|
|
18
|
+
export declare const RUNTIME_CONTRACT_V1: RuntimeContract;
|
|
19
|
+
/**
|
|
20
|
+
* v2 — adds the Solid-style (but ours) template-clone primitives. A future
|
|
21
|
+
* template-clone backend targets this contract; the runtime gains template()/
|
|
22
|
+
* cloneTemplate()/walk() at the same time.
|
|
23
|
+
*/
|
|
24
|
+
export declare const RUNTIME_CONTRACT_V2: RuntimeContract;
|
|
25
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/codegen/contract.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAcjC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAIjC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1 — the imperative fine-grained runtime, locked by the @fluixi/dom contract
|
|
3
|
+
* tests (createNativeElement/insert/spread/delegateEvents/createComponent + the
|
|
4
|
+
* control-flow components).
|
|
5
|
+
*/
|
|
6
|
+
export const RUNTIME_CONTRACT_V1 = {
|
|
7
|
+
version: 1,
|
|
8
|
+
module: '@fluixi/dom',
|
|
9
|
+
symbols: [
|
|
10
|
+
'createNativeElement',
|
|
11
|
+
'insert',
|
|
12
|
+
'spread',
|
|
13
|
+
'setAttribute',
|
|
14
|
+
'delegateEvents',
|
|
15
|
+
'createComponent',
|
|
16
|
+
'createMemo',
|
|
17
|
+
'untrack',
|
|
18
|
+
'Show', 'For', 'Index', 'Switch', 'Match', 'Dynamic', 'ErrorBoundary',
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* v2 — adds the Solid-style (but ours) template-clone primitives. A future
|
|
23
|
+
* template-clone backend targets this contract; the runtime gains template()/
|
|
24
|
+
* cloneTemplate()/walk() at the same time.
|
|
25
|
+
*/
|
|
26
|
+
export const RUNTIME_CONTRACT_V2 = {
|
|
27
|
+
version: 2,
|
|
28
|
+
module: '@fluixi/dom',
|
|
29
|
+
symbols: [...RUNTIME_CONTRACT_V1.symbols, 'template', 'cloneTemplate', 'walk'],
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},t={version:2,module:"@fluixi/dom",symbols:[...e.symbols,"template","cloneTemplate","walk"]};export{e as RUNTIME_CONTRACT_V1,t as RUNTIME_CONTRACT_V2};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var C=Object.create;var m=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var P=(e,t)=>{for(var r in t)m(e,r,{get:t[r],enumerable:!0})},S=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of X(t))!k.call(e,i)&&i!==r&&m(e,i,{get:()=>t[i],enumerable:!(n=I(t,i))||n.enumerable});return e};var A=(e,t,r)=>(r=e!=null?C(b(e)):{},S(t||!e||!e.__esModule?m(r,"default",{value:e,enumerable:!0}):r,e)),w=e=>S(m({},"__esModule",{value:!0}),e);var q={};P(q,{buildIR:()=>g});module.exports=w(q);var s=require("@babel/core"),x=A(require("@babel/generator"),1);var d={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},H={version:2,module:"@fluixi/dom",symbols:[...d.symbols,"template","cloneTemplate","walk"]};var T={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function O(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function h(e){return O(e)?e:JSON.stringify(e)}function j(e){return e.expr!==void 0?e.reactive?`() => (${e.expr})`:`(${e.expr})`:JSON.stringify(e.literal??!0)}function _(e){return e.expr!==void 0?`(${e.expr})`:JSON.stringify(e.literal??!0)}function M(e,t,r){let n=e.filter(a=>a.kind==="spread"),o=e.filter(a=>a.kind!=="spread").map(a=>`${h(a.name)}: ${j(a)}`);t!=null&&o.push(`children: ${t}`);let p=`{ ${o.join(", ")} }`;return n.length>0?(r.add("mergeProps"),`mergeProps(${n.map(a=>a.expr).join(", ")}, ${p})`):p}function y(e,t){return e.length===1?u(e[0],t):`[${e.map(r=>u(r,t)).join(", ")}]`}function E(e,t,r,n){n.add("createMemo"),n.add("createComponent");let i=t.filter(c=>c.kind==="spread"),p=t.filter(c=>c.kind!=="spread").map(c=>`get ${h(c.name)}() { return ${_(c)}; }`);r.length>0&&p.push(`get children() { return ${y(r,n)}; }`);let a=`{ ${p.join(", ")} }`;return i.length>0&&(n.add("mergeProps"),a=`mergeProps(${i.map(c=>c.expr).join(", ")}, ${a})`),`createMemo(() => createComponent(${e}, ${a}))`}function u(e,t){switch(e.kind){case"text":return JSON.stringify(e.value);case"expr":return e.reactive?`() => (${e.code})`:`(${e.code})`;case"fragment":return e.children.length===0?"null":y(e.children,t);case"component":return E(e.name,e.props,e.children,t);case"control":{let r=T[e.control]??e.control;return t.add(r),E(r,e.props,e.children,t)}case"element":{t.add("createNativeElement");let r=JSON.stringify(e.tag),n="_el$",i=[],o=e.svg?`${r}, true`:r;if(i.push(`const ${n} = createNativeElement(${o});`),e.props.length>0){t.add("spread");let p=e.svg?", isSVG: true":"";i.push(`spread({ element: ${n}, props: ${M(e.props,null,t)}${p} });`)}for(let p of e.children){t.add("insert");let a=u(p,t),c=p.kind==="expr"&&p.reactive||p.kind==="component"||p.kind==="control";i.push(c?`insert(${n}, ${a}, null);`:`insert(${n}, ${a});`)}return i.push(`return ${n};`),`(() => { ${i.join(" ")} })()`}}}var $={name:"imperative",contract:d,emit(e,t){let r=new Set;return{code:u(e,r),imports:Array.from(r)}}};var L=x.default.default??x.default;function J(e){return L(e,{concise:!0}).code}function F(e,t){let r=s.types.cloneNode(e,!0),n=s.types.file(s.types.program([s.types.expressionStatement(r)])),i=!1;return(0,s.traverse)(n,{"JSXElement|JSXFragment"(o){let p=o.node,{code:a,imports:c}=$.emit(g(p,t),{});for(let v of c)t.add(v);let R=s.template.expression(a,{placeholderPattern:!1})();o.replaceWith(R),o.skip(),i=!0}}),i?n.program.body[0].expression:e}function f(e,t){return J(F(e,t))}var B=new Set(["svg","path","circle","rect","line","polygon","polyline","ellipse","g","defs","clipPath","text"]),V=/^on[A-Z]/,D=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function G(e){if(s.types.isJSXIdentifier(e)){let t=e.name[0]!==e.name[0].toLowerCase();return{tag:e.name,component:t}}return s.types.isJSXMemberExpression(e)?{tag:J(e),component:!0}:s.types.isJSXNamespacedName(e)?{tag:`${e.namespace.name}:${e.name.name}`,component:!1}:{tag:"div",component:!1}}function K(e){return s.types.isJSXIdentifier(e)?e.name==="class"?"className":e.name:s.types.isJSXNamespacedName(e)?`${e.namespace.name}:${e.name.name}`:"unknown"}function l(e){return s.types.isCallExpression(e)||s.types.isOptionalCallExpression(e)?!0:s.types.isMemberExpression(e)||s.types.isOptionalMemberExpression(e)?!(!e.computed&&s.types.isIdentifier(e.property,{name:"children"})):s.types.isConditionalExpression(e)?l(e.test)||l(e.consequent)||l(e.alternate):s.types.isLogicalExpression(e)||s.types.isBinaryExpression(e)?l(e.left)||l(e.right):s.types.isTemplateLiteral(e)?e.expressions.some(t=>l(t)):!1}function U(e,t){let r=K(e.name),n=V.test(r),o={name:r,kind:n?"event":"attr"};n&&(o.event={name:r.slice(2).toLowerCase(),delegated:D.has(r.slice(2).toLowerCase())});let p=e.value;if(p==null)return o.literal=!0,o;if(s.types.isStringLiteral(p))return o.literal=p.value,o;if(s.types.isJSXExpressionContainer(p)&&!s.types.isJSXEmptyExpression(p.expression)){let a=p.expression;return s.types.isStringLiteral(a)||s.types.isNumericLiteral(a)||s.types.isBooleanLiteral(a)?(o.literal=a.value,o):(o.expr=f(a,t),o.reactive=n?!1:l(a),(s.types.isJSXElement(a)||s.types.isJSXFragment(a))&&(o.jsxElement=!0),o)}return o.literal=!0,o}function Z(e,t){let r=[];for(let n of e)s.types.isJSXSpreadAttribute(n)?r.push({name:"",kind:"spread",expr:f(n.argument,t)}):s.types.isJSXAttribute(n)&&r.push(U(n,t));return r}function z(e){let t=e.split(/\r\n|\n|\r/),r=0;for(let i=0;i<t.length;i++)/[^ \t]/.test(t[i])&&(r=i);let n="";for(let i=0;i<t.length;i++){let o=t[i].replace(/\t/g," ");i!==0&&(o=o.replace(/^ +/,"")),i!==t.length-1&&(o=o.replace(/ +$/,"")),o&&(i!==r&&(o+=" "),n+=o)}return n}function N(e,t){let r=[];for(let n of e)if(s.types.isJSXText(n)){let i=z(n.value);i&&r.push({kind:"text",value:i})}else if(s.types.isJSXExpressionContainer(n)){if(!s.types.isJSXEmptyExpression(n.expression)){let i=n.expression;r.push({kind:"expr",code:f(i,t),reactive:l(i)})}}else s.types.isJSXElement(n)||s.types.isJSXFragment(n)?r.push(g(n,t)):s.types.isJSXSpreadChild(n)&&r.push({kind:"expr",code:f(n.expression,t),reactive:!1});return r}function g(e,t=new Set){if(s.types.isJSXFragment(e))return{kind:"fragment",children:N(e.children,t)};let{tag:r,component:n}=G(e.openingElement.name),i=Z(e.openingElement.attributes,t),o=N(e.children,t);return n?{kind:"component",name:r,props:i,children:o}:{kind:"element",tag:r,svg:B.has(r),props:i,children:o,static:!1}}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Babel front-end: build the host-agnostic IR from a JSX AST node.
|
|
3
|
+
*
|
|
4
|
+
* This is the parsing-end half of the pipeline (AST -> IR); the imperative
|
|
5
|
+
* backend's emit() is the codegen half (IR -> code). Keeping the JSX analysis
|
|
6
|
+
* here and the code generation in the backend is what lets a future swc
|
|
7
|
+
* front-end reuse the exact same backend.
|
|
8
|
+
*
|
|
9
|
+
* JSX can appear nested inside arbitrary expressions (render-props, ternaries,
|
|
10
|
+
* `fallback={<p/>}`, `arr.map(x => <li/>)`, `() => cond && <div/>`, …). The IR
|
|
11
|
+
* models prop/child *expressions* as code strings, so any JSX inside such an
|
|
12
|
+
* expression is recursively compiled (build-ir -> emit) and spliced back in,
|
|
13
|
+
* with the runtime symbols it uses collected into `used` for import injection.
|
|
14
|
+
*/
|
|
15
|
+
import { types as t } from '@babel/core';
|
|
16
|
+
import type { IRNode } from '../../ir/nodes.js';
|
|
17
|
+
/**
|
|
18
|
+
* Build IR from a JSXElement or JSXFragment. `used` accumulates the runtime
|
|
19
|
+
* symbols emitted for any JSX nested inside expressions (so the caller can
|
|
20
|
+
* inject the right imports).
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildIR(node: t.JSXElement | t.JSXFragment, used?: Set<string>): IRNode;
|
|
23
|
+
//# sourceMappingURL=build-ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-ir.d.ts","sourceRoot":"","sources":["../../../src/frontend/babel/build-ir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,IAAI,CAAC,EAAsB,MAAM,aAAa,CAAC;AAG7D,OAAO,KAAK,EACV,MAAM,EAGP,MAAM,mBAAmB,CAAC;AA8L3B;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,MAAM,CAYjG"}
|