Skip to content

Commit 4615ef6

Browse files
committed
updates, remove react, solid, preact bridge code as universal won't be supporting them
1 parent f83258f commit 4615ef6

8 files changed

Lines changed: 22 additions & 237 deletions

File tree

.agents/skills/building/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ comptime if(intrinsics::is_interpretation()) {
157157

158158
We test most libraries in the tests above (`lang/tests/build.lab`) but some libraries like:
159159
- `html_cbi`, `css_cbi`, `js_cbi`, `components`
160-
- `react_cbi`, `preact_cbi`, `solid_cbi`, `universal_cbi`
160+
- `universal_cbi`
161161

162162
These are compiler plugins, tested via a separate executable:
163163

@@ -178,7 +178,7 @@ Helpful flags:
178178
If you modify anything inside the [server](/server/) directory, note that it's part of the LSP target.
179179

180180
These modules are all LSP-related and require the LSP server running to verify:
181-
- `html_ide`, `css_ide`, `js_ide`, `react_ide`, `preact_ide`, `solid_ide`, `universal_ide`, `md_ide`
181+
- `html_ide`, `css_ide`, `js_ide`, `universal_ide`, `md_ide`
182182

183183
```bash
184184
# Build LSP

.agents/skills/cbi_plugin_api/SKILL.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,7 @@ These are the plugins shipped with the compiler. Each demonstrates different CBI
144144
| `css_cbi` | `lang/libs/css_cbi/` | `#css` macro | Parses CSS properties, generates style strings |
145145
| `js_cbi` | `lang/libs/js_cbi/` | `#js` macro | Inlines JavaScript code into the JS bundle |
146146
| `universal_cbi` | `lang/libs/universal_cbi/` | `#universal` component | SSR + hydration — generates server function + JS hydration |
147-
| `react_cbi` | `lang/libs/react_cbi/` | `#react` component | React-style JSX → runtime calls |
148-
| `preact_cbi` | `lang/libs/preact_cbi/` | `#preact` component | Preact-style JSX → runtime calls |
149-
| `solid_cbi` | `lang/libs/solid_cbi/` | `#solid` component | SolidJS-style JSX |
147+
150148
| `md_cbi` | `lang/libs/md_cbi/` | Markdown processing | Converts markdown to HTML |
151149

152150
### Example: html_cbi Structure

.agents/skills/macro_code_gen/SKILL.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
name: Macro Code gen
33
description:
4-
How libraries (html_cbi, preact_cbi, react_cbi, solid_cbi, universal_cbi) generate code
4+
How libraries (html_cbi, universal_cbi) generate code
55
---
66

77
When you write in chemical
@@ -47,13 +47,12 @@ func my_html(page : &mut HtmlPage, name : &std::string_view) {
4747

4848
This is how we handle chemical values, But you may notice that we support top level macros
4949

50-
`#preact`, `#react`, `#solid`, `#universal` All these component framework libraries are top level macros. The reason being
51-
that these handle components and that's why.
50+
`#universal` is the component macro. It handles SSR + hydration for server-rendered interactive UI.
5251

53-
for example
52+
For example:
5453

5554
```chemical
56-
#preact Greeting(props) {
55+
#universal Greeting(props) {
5756
return <div>Hello {props.name}</div>
5857
}
5958
```
@@ -75,6 +74,6 @@ The function names maybe a little different, but they accomplish similar logic,
7574
universal lib generate a function that takes two more parameters, an SsrAttributeList, content for the children
7675
universal lib also generates in both bundles, HTML that is server side rendered (from the component) and then a js function
7776
that would hydrate the emitted html.
78-
universal components are fast and they render everywhere, they work in react, preact and solid components. They work in `#html` too.
77+
universal components are fast and they render everywhere. They work in `#html` blocks too.
7978

8079
For more information on universal components, load the `universal` skill. For developing new compiler plugins or understanding the plugin API, load the `cbi_plugin_api` skill. For understanding the compiler intrinsics and reflection APIs that macros can use at compile time, load the `intrinsics_compiler_reflection` skill.

.agents/skills/universal/SKILL.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ description: Diagnose, fix, and implement features in the Chemical universal com
88
Universal library is present in `lang/libs/universal_cbi`, its a macro processing library, it handles
99
specifically `#univeral` macros, for examples you can look for components present in `lang/libs/components`
1010

11-
Universal library emits components, Universal library is meant for server side rendering + hydration, The reason
12-
its called universal is because we have libraries like `react_cbi`, `preact_cbi`, `solid_cbi`, they do not do hydration + ssr,
13-
instead they just translate jsx to runtime calls, which is way easier. Universal components are supposed to
14-
work inside react, preact or solid components, we have another `#html` macro, library `html_cbi`, universal components
15-
work inside the html macro too. So yeah, Universal components work everywhere, they are fast because they do ssr + hydration.
11+
Universal library emits components, Universal library is meant for server side rendering + hydration.
12+
Universal components work inside `#html` blocks (processed by `html_cbi`) and are the primary way
13+
to build interactive UI. They do SSR + hydration for fast initial paint and full interactivity.
14+
15+
> **Note:** React, Preact, and Solid framework bridges (`react_cbi`, `preact_cbi`, `solid_cbi`) have been
16+
> removed. The universal component system is the only supported component model.
1617
1718
### How universal performs ssr + hydration.
1819

@@ -22,14 +23,13 @@ third the text for the children, yes we pass children as `SsrText` (a struct in
2223

2324
The server function does two things, it appends a js function that would perform hydration into the js bundle, It also appends the server side rendered html
2425
to the html bundle.
25-
A trick used by `react_cbi`, `solid_cbi` and `preact_cbi`, they actually capture this html and put it into the js bundle.
26+
The universal component system captures this html and puts it into the js bundle for hydration.
2627

2728
When I say js bundle or html bundle, A struct HtmlPage present in `lang/libs/page` is used for each page, it contains strings
2829
in which we append, `pageHtml`, `pageHeadJs`, `pageJs`, these fields are used to write the final output.
2930

30-
`react_cbi`, `solid_cbi` and `preact_cbi` write their components to `pageHeadJs`, because we use umd bundles, so that everything is rendered
31-
without flash of unrendered components, `universal_cbi` however appends to the `pageJs`, so its components are present in the js loaded at the end of body
32-
this means we have to use a queue to hydrate universal components, once they have been rendered.
31+
`universal_cbi` appends to the `pageJs`, so its components are present in the js loaded at the end of body.
32+
This means we have to use a queue (`$__uni_hydration_queue`) to hydrate universal components once they have been rendered.
3333

3434
One very important thing to note:
3535

lang/libs/html_cbi/src/converter/language/component.ch

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,8 @@ func (converter : &mut ASTConverter) convertHtmlComponent(element : *mut HtmlEle
176176
// appendUIntCall.get_args().push(uIdVal as *mut Value);
177177
// converter.vec.push(appendUIntCall as *mut ASTNode);
178178

179-
// Emit " data-u-comp="Name">
179+
// Emit closing quote and >
180180
converter.str.append('"');
181-
// converter.str.append_view(" data-u-comp=\"")
182-
// get_module_scoped_name(signature.functionNode as *mut ASTNode, signature.name, converter.str);
183-
// converter.str.append('"');
184181
converter.str.append('>');
185182
converter.put_chain_in();
186183

@@ -312,22 +309,7 @@ func (converter : &mut ASTConverter) convertHtmlComponent(element : *mut HtmlEle
312309

313310
s.append_view("<script>")
314311

315-
if(signature.mountStrategy == MountStrategy.Preact) {
316-
// Preact Mount Strategy
317-
s.append_view("$_pm(document.currentScript, ")
318-
get_module_scoped_name(signature.functionNode as *mut ASTNode, signature.name, &mut *s)
319-
s.append_view(", {")
320-
} else if(signature.mountStrategy == MountStrategy.React) {
321-
// React Mount Strategy
322-
s.append_view("$_rm(document.currentScript, ")
323-
get_module_scoped_name(signature.functionNode as *mut ASTNode, signature.name, &mut *s)
324-
s.append_view(", {")
325-
} else if(signature.mountStrategy == MountStrategy.Solid) {
326-
// Solid Mount Strategy
327-
s.append_view("$_sm(document.currentScript, ")
328-
get_module_scoped_name(signature.functionNode as *mut ASTNode, signature.name, &mut *s)
329-
s.append_view(", {")
330-
} else if(signature.mountStrategy == MountStrategy.Universal) {
312+
if(signature.mountStrategy == MountStrategy.Universal) {
331313
// Universal Mount Strategy (HTML-first, no framework dependency)
332314
s.append_view("$_um(document.currentScript, ")
333315
get_module_scoped_name(signature.functionNode as *mut ASTNode, signature.name, &mut *s)

lang/libs/page/src/page.ch

Lines changed: 1 addition & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -418,61 +418,10 @@ public struct HtmlPage {
418418
appendViewportMeta();
419419
}
420420

421-
// TODO: why is the preact setup so large, fix that
422-
func defaultPreactSetup(&mut self) {
423-
pageHead.append_view(std::string_view("""<script src="https://unpkg.com/preact/dist/preact.min.js"></script><script src="https://unpkg.com/preact/hooks/dist/hooks.umd.js"></script>"""))
424-
pageHeadJs.append_view(std::string_view("""window.$_p = preact;window.$_ph = preactHooks; window.$_pm = (e,c,p) => {const P = document.createDocumentFragment(); $_p.render($_p.h(c, p || {}), P); e.replaceWith(P); };"""))
425-
// universal component bridge for preact
426-
pageHeadJs.append_view(std::string_view("""
427-
function UniPreactBridge({ html, fnName, props }) {
428-
const ref = $_ph.useRef(null);
429-
$_ph.useLayoutEffect(() => {
430-
const target = ref.current;
431-
window.$__uni_dispatch(fnName, target, props);
432-
}, [fnName, props]);
433-
return $_p.h('div', {
434-
ref,
435-
style: "display: contents",
436-
dangerouslySetInnerHTML: { __html: html }
437-
});
438-
}
439-
const $p_uni_ch = (html, fnName, props) => $_p.h(UniPreactBridge, { html, fnName, props });
440-
"""))
441-
}
442-
443-
func reactHeadJs(&mut self) {
444-
pageHeadJs.append_view(std::string_view("""window.$_r = React; window.$_rd = ReactDOM; window.$_rm = (e, c, p) => { const P = document.createElement("div"); e.replaceWith(P); $_rd.createRoot(P).render($_r.createElement(c, p || {})); }"""));
445-
pageHeadJs.append_view(std::string_view("""
446-
function UniReactBridge({ html, fnName, props }) {
447-
const ref = $_r.useRef(null);
448-
$_r.useLayoutEffect(() => {
449-
const target = ref.current;
450-
window.$__uni_dispatch(fnName, target, props);
451-
}, [fnName, props]);
452-
return $_r.createElement('div', {
453-
ref,
454-
style: { display: 'contents' },
455-
dangerouslySetInnerHTML: { __html: html }
456-
});
457-
}
458-
const $r_uni_ch = (html, fnName, props) => $_r.createElement(UniReactBridge, { html, fnName, props });
459-
"""))
460-
}
461-
462-
func defaultDevelopmentReactSetup(&mut self) {
463-
pageHead.append_view(std::string_view("""<script src="https://unpkg.com/react@18/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>"""))
464-
reactHeadJs()
465-
}
466-
467-
func defaultReactSetup(&mut self) {
468-
pageHead.append_view(std::string_view("""<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>"""))
469-
reactHeadJs()
470-
}
471-
472421
func defaultUniversalSetup(&mut self) {
473422
// we must not put anything else in the head js
474423
// everything else must go into body js
475-
// this is just required for react, solid and preact integration to work
424+
// universal component hydration runtime
476425
pageHeadJs.append_view(std::string_view("""
477426
window.$__uni_hydration_queue = []
478427
window.$__uni_error = ((message, details = "", cause = null) => {
@@ -1281,59 +1230,6 @@ window.$__universal_flush = function() {
12811230
pageJsEnd.append_view(std::string_view("window.$__universal_flush();"))
12821231
}
12831232

1284-
func asynchronousSolidSetup(&mut self) {
1285-
pageHead.append_view(std::string_view("""<script type="module">
1286-
import * as solid from 'https://esm.sh/solid-js@1.9.10';
1287-
import * as web from 'https://esm.sh/solid-js@1.9.10/web';
1288-
import h from 'https://esm.sh/solid-js@1.9.10/h';
1289-
window.$_s = solid;
1290-
window.$_sw = web;
1291-
window.$_sh = h;
1292-
if(window.$_sc) window.$_sc();
1293-
</script>
1294-
<script>
1295-
let $_sr_queue = [];
1296-
function $_sr(e, comp, props) {
1297-
const mount = document.createElement('div');
1298-
e.replaceWith(mount);
1299-
$_sw.render(() => comp(props || {}), mount);
1300-
}
1301-
window.$_sc = () => {
1302-
for(var i = 0; i < $_sr_queue.length; i++) {
1303-
const q = $_sr_queue[i];
1304-
$_sr(q[0], q[1], q[2])
1305-
}
1306-
$_sr_queue = [];
1307-
}
1308-
window.$_sm = (e, comp, props) => {
1309-
if(window.$_sw) {
1310-
$_sr(e, comp, props)
1311-
} else {
1312-
$_sr_queue.push([e, comp, props])
1313-
}
1314-
};
1315-
</script>"""))
1316-
}
1317-
1318-
func defaultSolidSetup(&mut self) {
1319-
pageHead.append_view(std::string_view("""<script src="https://unpkg.com/solid-umd@1.9.10/dist/solid.min.js"></script><script src="https://unpkg.com/solid-umd@1.9.10/dist/solid-web.min.js"></script><script src="https://unpkg.com/solid-umd@1.9.10/dist/solid-h.min.js"></script>"""))
1320-
pageHeadJs.append_view(std::string_view("""window.$_s = Solid; window.$_sw = SolidWeb; window.$_sh = SolidH.default || SolidH; window.$_sm = (e, comp, props) => { const mount = document.createElement('div'); e.replaceWith(mount); $_sw.render(() => comp(props || {}), mount); };"""))
1321-
pageHeadJs.append_view(std::string_view("""
1322-
function UniSolidBridge(props) {
1323-
let el;
1324-
$_s.onMount(() => {
1325-
window.$__uni_dispatch(props.fnName, el, props.props);
1326-
});
1327-
return $_sh("div", {
1328-
ref: (r) => el = r,
1329-
style: { display: "contents" },
1330-
innerHTML: props.html
1331-
});
1332-
}
1333-
const $s_uni_ch = (html, fnName, props) => $_sh(UniSolidBridge, { html, fnName, props });
1334-
"""))
1335-
}
1336-
13371233
func getFinalizedPageJs(&self) : std::string {
13381234
var str = std::string();
13391235
str.reserve(pageJs.size() + pageJsEnd.size())

lang/libs/page/src/ssr.ch

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,8 @@ public func renderCssAttrValue(page : &mut HtmlPage, attrVal : &SsrAttributeValu
595595
writeJsPrimitiveAttrValue(page, &mut page.pageCss, attrVal)
596596
}
597597

598-
// this function allows libraries like preact, solid and react to move rendered html to js buffer
599-
// then they send the html to a function that creates an element out of it
600-
// then they hydrate that element, this is usually done for a universal component that renders html for ssr
598+
// This function moves rendered html to the js buffer for hydration.
599+
// Universal components use this to capture SSR HTML and hydrate it on the client.
601600
public func move_html_to_js_with_lambda_start(page : &mut HtmlPage, index : size_t) {
602601
page.pageHeadJs.append_view("\n(() => { const html = `");
603602
const delta_size = page.pageHtml.size() - index;

lang/libs/universal_cbi/src/converter/converter_jsx.ch

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -55,85 +55,6 @@ func (converter : &mut JsConverter) convertJSXComponent(element : *mut JsJSXElem
5555
}
5656

5757
const signature = element.componentSignature;
58-
if(signature.mountStrategy != MountStrategy.Universal) {
59-
converter.put_chain_in();
60-
61-
const builder = converter.builder;
62-
const location = intrinsics::get_raw_location();
63-
64-
// signature.name(page)
65-
var base = builder.make_identifier(&signature.name, signature.functionNode, false, location);
66-
var pageId = builder.make_identifier(std::string_view("page"), converter.support.pageNode, false, location);
67-
var call = builder.make_function_call_node(base, converter.parent, location);
68-
call.get_args().push(pageId);
69-
converter.vec.push(call);
70-
71-
converter.str.append_view("<script>");
72-
73-
const mountFn = switch(signature.mountStrategy) {
74-
MountStrategy.React => view("$_rm")
75-
MountStrategy.Preact => view("$_pm")
76-
MountStrategy.Solid => view("$_sm")
77-
default => view("$_dm")
78-
}
79-
80-
converter.str.append_view(&mountFn);
81-
converter.str.append_view("(document.currentScript, ");
82-
get_module_scoped_name(signature.functionNode, signature.name, &mut converter.str);
83-
converter.str.append_view(", {");
84-
85-
var attrCount = 0u;
86-
const attributes = &element.opening.attributes;
87-
for(var i : uint = 0; i < attributes.size(); i++) {
88-
const attrNode = attributes.get(i);
89-
if(attrNode.kind == JsNodeKind.JSXAttribute) {
90-
const attr = attrNode as *mut JsJSXAttribute;
91-
if(attr.name.equals("children")) continue;
92-
93-
if(attrCount > 0) converter.str.append_view(", ");
94-
converter.str.append_view(&attr.name);
95-
converter.str.append_view(": ");
96-
97-
if(attr.value == null) {
98-
converter.str.append_view("true");
99-
} else if(attr.value.kind == JsNodeKind.Literal) {
100-
converter.convertJsNode(attr.value);
101-
} else if(attr.value.kind == JsNodeKind.JSXExpressionContainer) {
102-
const container = attr.value as *mut JsJSXExpressionContainer;
103-
if(container.expression != null) {
104-
if(container.expression.kind == JsNodeKind.ChemicalValue) {
105-
const cv = container.expression as *mut JsChemicalValue;
106-
const cvType = cv.value.getType();
107-
const isStr = cvType != null && (cvType.getKind() == BaseTypeKind.String ||
108-
cvType.getKind() == BaseTypeKind.Pointer ||
109-
cvType.getKind() == BaseTypeKind.ExpressiveString);
110-
if(isStr) converter.str.append('"');
111-
112-
converter.put_chain_in();
113-
converter.put_chemical_value_in(cv.value);
114-
115-
if(isStr) {
116-
converter.put_char_chain('"');
117-
}
118-
} else if(container.expression.kind == JsNodeKind.MemberAccess) {
119-
const mem = container.expression as *mut JsMemberAccess;
120-
if(mem.object != null && mem.object.kind == JsNodeKind.Identifier && converter.is_component_props_name((mem.object as *mut JsIdentifier).value)) {
121-
converter.put_chain_in();
122-
const v = converter.make_ssr_prop_v_call(mem.property);
123-
const renderCall = converter.render_ssr_value_call(v);
124-
converter.vec.push(renderCall);
125-
}
126-
}
127-
}
128-
}
129-
attrCount++;
130-
}
131-
}
132-
133-
converter.str.append_view("});</script>");
134-
converter.put_chain_in();
135-
return;
136-
}
13758

13859
const hash = signature.functionNode.getEncodedLocation();
13960

@@ -262,11 +183,6 @@ func (converter : &mut JsConverter) convertJSXComponent(element : *mut JsJSXElem
262183
return;
263184
}
264185

265-
if(element.componentSignature != null && element.componentSignature.mountStrategy != MountStrategy.Universal) {
266-
converter.str.append_view("null");
267-
return;
268-
}
269-
270186
if(element.componentSignature != null && converter.target == BufferType.JavaScript) {
271187
converter.put_chain_in();
272188
const signature = element.componentSignature;
@@ -344,11 +260,6 @@ func (converter : &mut JsConverter) convertJSXComponent(element : *mut JsJSXElem
344260
return;
345261
}
346262

347-
if(element.componentSignature != null && element.componentSignature.mountStrategy != MountStrategy.Universal) {
348-
converter.str.append_view("null");
349-
return;
350-
}
351-
352263
converter.str.append_view("$_ur.createElement(");
353264
if(tagNameNode.kind == JsNodeKind.Identifier) {
354265
if(element.componentSignature != null) get_module_scoped_name(element.componentSignature.functionNode, tagName, &mut converter.str);

0 commit comments

Comments
 (0)