hadars 0.4.2 → 1.0.1

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/README.md CHANGED
@@ -21,30 +21,30 @@ Bring your own router (or none), keep your components as plain React, and get SS
21
21
  ## Benchmarks
22
22
 
23
23
  <!-- BENCHMARK_START -->
24
- > Last run: 2026-04-02 · 120s · 100 connections · Bun runtime
25
- > hadars is **9.3x faster** in requests/sec
24
+ > Last run: 2026-04-17 · 120s · 100 connections · Bun runtime
25
+ > hadars is **9.5x faster** in requests/sec
26
26
 
27
27
  **Throughput** (autocannon, 120s)
28
28
 
29
29
  | Metric | hadars | Next.js |
30
30
  |---|---:|---:|
31
- | Requests/sec | **158** | 17 |
32
- | Latency median | **634 ms** | 2754 ms |
33
- | Latency p99 | **1031 ms** | 4140 ms |
34
- | Throughput | **44.97** MB/s | 9.67 MB/s |
35
- | Peak RSS | 1001.1 MB | **477.2 MB** |
36
- | Avg RSS | 778.8 MB | **426.8 MB** |
37
- | Build time | 0.6 s | 6.0 s |
31
+ | Requests/sec | **218** | 23 |
32
+ | Latency median | **446 ms** | 2421 ms |
33
+ | Latency p99 | **838 ms** | 3244 ms |
34
+ | Throughput | **62.07** MB/s | 12.6 MB/s |
35
+ | Peak RSS | 1032.7 MB | **514.0 MB** |
36
+ | Avg RSS | 842.2 MB | **462.8 MB** |
37
+ | Build time | 1.1 s | 5.3 s |
38
38
 
39
39
  **Page load** (Playwright · Chromium headless · median)
40
40
 
41
41
  | Metric | hadars | Next.js |
42
42
  |---|---:|---:|
43
- | TTFB | **17 ms** | 45 ms |
44
- | FCP | **92 ms** | 140 ms |
45
- | DOMContentLoaded | **37 ms** | 127 ms |
46
- | Load | **118 ms** | 172 ms |
47
- | Peak RSS | 479.5 MB | **295.5 MB** |
43
+ | TTFB | **15 ms** | 33 ms |
44
+ | FCP | **76 ms** | 112 ms |
45
+ | DOMContentLoaded | **31 ms** | 101 ms |
46
+ | Load | **96 ms** | 139 ms |
47
+ | Peak RSS | 508.0 MB | **299.5 MB** |
48
48
  <!-- BENCHMARK_END -->
49
49
 
50
50
  ## Quick start
@@ -240,6 +240,45 @@ const config: HadarsOptions = {
240
240
  export default config;
241
241
  ```
242
242
 
243
+ ### swcPlugins example
244
+
245
+ SWC plugins let you apply compiler transforms (Relay, emotion, styled-components, etc.) to every file in both the client and SSR bundles.
246
+
247
+ ```ts
248
+ import type { HadarsOptions } from 'hadars';
249
+
250
+ const config: HadarsOptions = {
251
+ entry: 'src/App.tsx',
252
+ swcPlugins: [
253
+ ['@swc/plugin-relay', { rootDir: process.cwd(), artifactDirectory: 'src/__generated__' }],
254
+ ],
255
+ };
256
+
257
+ export default config;
258
+ ```
259
+
260
+ **Plugin version compatibility** — SWC plugins are compiled against a specific version of `swc_core` and will silently fail or crash if the version doesn't match rspack's internal SWC. For `@rspack/core@1.6.8` the compatible plugins are:
261
+
262
+ | Plugin | Version |
263
+ |---|---|
264
+ | `@swc/plugin-relay` | `10.0.0` |
265
+ | `@swc/plugin-emotion` | `12.0.0` |
266
+ | `@swc/plugin-styled-components` | `10.0.0` |
267
+ | `@swc/plugin-styled-jsx` | `11.0.0` |
268
+ | `@swc/plugin-jest` | `10.0.0` |
269
+ | `@swc/plugin-formatjs` | `7.0.0` |
270
+ | `@swc/plugin-transform-imports` | `10.0.0` |
271
+ | `@swc/plugin-loadable-components` | `9.0.0` |
272
+ | `@swc/plugin-prefresh` | `10.0.0` |
273
+ | `swc-plugin-css-modules` | `6.0.0` |
274
+ | `swc-plugin-pre-paths` | `6.0.0` |
275
+ | `swc-plugin-transform-remove-imports` | `7.0.0` |
276
+ | `@lingui/swc-plugin` | `5.9.0` |
277
+
278
+ Install the exact version listed — do **not** use `latest` or a semver range. The full compatibility matrix for other rspack versions is at [plugins.swc.rs](https://plugins.swc.rs).
279
+
280
+ > The `@swc/core` package in hadars's `optionalDependencies` is used only by the hadars loader for its own AST transforms. It is a separate concern from the SWC version bundled inside rspack that runs your plugins.
281
+
243
282
  ### Error monitoring example
244
283
 
245
284
  ```ts
@@ -0,0 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ export {
9
+ __require
10
+ };
@@ -6,8 +6,12 @@ import {
6
6
  SUSPENSE_TYPE,
7
7
  createElement
8
8
  } from "./chunk-OZUZS2PD.js";
9
+ import {
10
+ __require
11
+ } from "./chunk-3RG5ZIWI.js";
9
12
 
10
13
  // src/slim-react/renderContext.ts
14
+ import { createRequire as _nodeCreateRequire } from "module";
11
15
  var MAP_KEY = "__slimReactContextMap";
12
16
  var _g = globalThis;
13
17
  if (!("__slimReactContextMap" in _g)) _g[MAP_KEY] = null;
@@ -29,8 +33,7 @@ function restoreUnsuspend(u) {
29
33
  function getContextValue(context) {
30
34
  const map = _g[MAP_KEY];
31
35
  if (map && map.has(context)) return map.get(context);
32
- const c = context;
33
- return "_defaultValue" in c ? c._defaultValue : c._currentValue;
36
+ return context._currentValue;
34
37
  }
35
38
  function pushContextValue(context, value) {
36
39
  let map = _g[MAP_KEY];
@@ -38,8 +41,7 @@ function pushContextValue(context, value) {
38
41
  map = /* @__PURE__ */ new Map();
39
42
  _g[MAP_KEY] = map;
40
43
  }
41
- const c = context;
42
- const prev = map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
44
+ const prev = map.has(context) ? map.get(context) : context._currentValue;
43
45
  map.set(context, value);
44
46
  return prev;
45
47
  }
@@ -144,13 +146,40 @@ function getTreeId() {
144
146
  const stripped = (id & ~(1 << 31 - Math.clz32(id))).toString(32);
145
147
  return stripped + overflow;
146
148
  }
149
+ var _detectReact = () => {
150
+ if (typeof __HADARS_REACT_MAJOR__ !== "undefined") {
151
+ const major = parseInt(String(__HADARS_REACT_MAJOR__), 10);
152
+ return {
153
+ major,
154
+ // Exact patch version is unknown from the define alone; use a
155
+ // representative fallback. Most libraries only check the major.
156
+ version: major < 19 ? "18.3.1" : "19.1.1"
157
+ };
158
+ }
159
+ const parse = (ver) => ({ major: parseInt(ver.split(".")[0], 10), version: ver });
160
+ try {
161
+ return parse(__require("react").version);
162
+ } catch {
163
+ }
164
+ try {
165
+ const req = _nodeCreateRequire(process.cwd() + "/__hadars__.js");
166
+ return parse(req("react").version);
167
+ } catch {
168
+ }
169
+ return { major: 19, version: "19.1.1" };
170
+ };
171
+ var _react = _detectReact();
172
+ var REACT_MAJOR = _react.major;
173
+ var REACT_VERSION = _react.version;
147
174
  function makeId() {
148
175
  const st = s();
149
176
  const treeId = getTreeId();
150
177
  const n = st.localIdCounter++;
151
- let id = "_R_" + st.idPrefix + treeId;
152
- if (n > 0) id += "H" + n.toString(32);
153
- return id + "_";
178
+ const suffix = n > 0 ? "H" + n.toString(32) : "";
179
+ if (REACT_MAJOR < 19) {
180
+ return ":" + st.idPrefix + "R" + treeId + suffix + ":";
181
+ }
182
+ return "_R_" + st.idPrefix + treeId + suffix + "_";
154
183
  }
155
184
 
156
185
  // src/slim-react/hooks.ts
@@ -243,8 +272,9 @@ function createContext(defaultValue) {
243
272
 
244
273
  // src/slim-react/dispatcher.ts
245
274
  import * as ReactNS from "react";
246
- var _reactInternalsKey = "__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE";
247
- var _internals = ReactNS[_reactInternalsKey];
275
+ var _r19 = ReactNS["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
276
+ var _r18Raw = !_r19 ? ReactNS["__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED"] : void 0;
277
+ var _r18 = _r18Raw?.ReactCurrentDispatcher ? _r18Raw : void 0;
248
278
  var slimDispatcher = {
249
279
  useId: makeId,
250
280
  readContext: (ctx) => getContextValue(ctx),
@@ -272,13 +302,21 @@ var slimDispatcher = {
272
302
  useHostTransitionStatus: () => false
273
303
  };
274
304
  function installDispatcher() {
275
- if (!_internals) return null;
276
- const prev = _internals.H;
277
- _internals.H = slimDispatcher;
278
- return prev;
305
+ if (_r19) {
306
+ const prev = _r19.H;
307
+ _r19.H = slimDispatcher;
308
+ return prev;
309
+ }
310
+ if (_r18) {
311
+ const prev = _r18.ReactCurrentDispatcher.current;
312
+ _r18.ReactCurrentDispatcher.current = slimDispatcher;
313
+ return prev;
314
+ }
315
+ return null;
279
316
  }
280
317
  function restoreDispatcher(prev) {
281
- if (_internals) _internals.H = prev;
318
+ if (_r19) _r19.H = prev;
319
+ else if (_r18) _r18.ReactCurrentDispatcher.current = prev;
282
320
  }
283
321
 
284
322
  // src/slim-react/render.ts
@@ -535,7 +573,7 @@ function writeAttributes(writer, props, isSvg, skip) {
535
573
  if (isSvg && key in SVG_ATTR_MAP) {
536
574
  attrName = SVG_ATTR_MAP[key];
537
575
  } else {
538
- attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key;
576
+ attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key === "contentEditable" && REACT_MAJOR < 19 ? "contenteditable" : key;
539
577
  }
540
578
  if (value === false || value == null) {
541
579
  if (value === false && (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-"))) {
@@ -744,7 +782,8 @@ function renderComponent(type, props, writer, isSvg, _suspenseRetries = 0) {
744
782
  const LazyComp = resolved?.default ?? resolved;
745
783
  return renderComponent(LazyComp, props, writer, isSvg);
746
784
  }
747
- if (typeOf === REACT_CONSUMER) {
785
+ const isConsumer = typeOf === REACT_CONSUMER || typeOf === REACT_CONTEXT && "_context" in type && !("value" in props);
786
+ if (isConsumer) {
748
787
  const ctx2 = type._context;
749
788
  const value = ctx2 ? getContextValue(ctx2) : void 0;
750
789
  const result2 = typeof props.children === "function" ? props.children(value) : null;
@@ -1130,7 +1169,12 @@ var Component = class {
1130
1169
  };
1131
1170
  var PureComponent = class extends Component {
1132
1171
  };
1133
- var version = "19.1.1";
1172
+ var version = REACT_VERSION;
1173
+ var __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED2 = {
1174
+ ReactCurrentDispatcher: { current: null },
1175
+ ReactCurrentBatchConfig: { transition: null },
1176
+ ReactCurrentOwner: { current: null }
1177
+ };
1134
1178
  var React = {
1135
1179
  // Hooks
1136
1180
  useState,
@@ -1174,7 +1218,9 @@ var React = {
1174
1218
  renderToReadableStream: renderToStream,
1175
1219
  renderPreflight,
1176
1220
  // Version
1177
- version
1221
+ version,
1222
+ // React 18 internals
1223
+ __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED2
1178
1224
  };
1179
1225
  var slim_react_default = React;
1180
1226
 
@@ -1213,5 +1259,6 @@ export {
1213
1259
  Component,
1214
1260
  PureComponent,
1215
1261
  version,
1262
+ __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED2 as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
1216
1263
  slim_react_default
1217
1264
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  renderPreflight,
3
3
  renderToString
4
- } from "./chunk-2TMQUXFL.js";
4
+ } from "./chunk-HIKMDNRB.js";
5
5
  import {
6
6
  createElement
7
7
  } from "./chunk-OZUZS2PD.js";
package/dist/cli.js CHANGED
@@ -147,25 +147,8 @@ var SLIM_ELEMENT = Symbol.for("react.element");
147
147
  var REACT19_ELEMENT = Symbol.for("react.transitional.element");
148
148
  var FRAGMENT_TYPE = Symbol.for("react.fragment");
149
149
  var SUSPENSE_TYPE = Symbol.for("react.suspense");
150
- // src/slim-react/jsx.ts
151
- function createElement(type, props, ...children) {
152
- const normalizedProps = { ...props || {} };
153
- if (children.length === 1) {
154
- normalizedProps.children = children[0];
155
- } else if (children.length > 1) {
156
- normalizedProps.children = children;
157
- }
158
- const key = normalizedProps.key ?? null;
159
- delete normalizedProps.key;
160
- return {
161
- $$typeof: SLIM_ELEMENT,
162
- type,
163
- props: normalizedProps,
164
- key
165
- };
166
- }
167
-
168
150
  // src/slim-react/renderContext.ts
151
+ import { createRequire as _nodeCreateRequire } from "node:module";
169
152
  var MAP_KEY = "__slimReactContextMap";
170
153
  var _g = globalThis;
171
154
  if (!("__slimReactContextMap" in _g))
@@ -189,8 +172,7 @@ function getContextValue(context) {
189
172
  const map = _g[MAP_KEY];
190
173
  if (map && map.has(context))
191
174
  return map.get(context);
192
- const c = context;
193
- return "_defaultValue" in c ? c._defaultValue : c._currentValue;
175
+ return context._currentValue;
194
176
  }
195
177
  function pushContextValue(context, value) {
196
178
  let map = _g[MAP_KEY];
@@ -198,8 +180,7 @@ function pushContextValue(context, value) {
198
180
  map = new Map;
199
181
  _g[MAP_KEY] = map;
200
182
  }
201
- const c = context;
202
- const prev = map.has(context) ? map.get(context) : ("_defaultValue" in c) ? c._defaultValue : c._currentValue;
183
+ const prev = map.has(context) ? map.get(context) : context._currentValue;
203
184
  map.set(context, value);
204
185
  return prev;
205
186
  }
@@ -304,14 +285,54 @@ function getTreeId() {
304
285
  const stripped = (id & ~(1 << 31 - Math.clz32(id))).toString(32);
305
286
  return stripped + overflow;
306
287
  }
288
+ var _detectReact = () => {
289
+ if (typeof __HADARS_REACT_MAJOR__ !== "undefined") {
290
+ const major = parseInt(String(__HADARS_REACT_MAJOR__), 10);
291
+ return {
292
+ major,
293
+ version: major < 19 ? "18.3.1" : "19.1.1"
294
+ };
295
+ }
296
+ const parse = (ver) => ({ major: parseInt(ver.split(".")[0], 10), version: ver });
297
+ try {
298
+ return parse(__require("react").version);
299
+ } catch {}
300
+ try {
301
+ const req = _nodeCreateRequire(process.cwd() + "/__hadars__.js");
302
+ return parse(req("react").version);
303
+ } catch {}
304
+ return { major: 19, version: "19.1.1" };
305
+ };
306
+ var _react = _detectReact();
307
+ var REACT_MAJOR = _react.major;
308
+ var REACT_VERSION = _react.version;
307
309
  function makeId() {
308
310
  const st = s();
309
311
  const treeId = getTreeId();
310
312
  const n = st.localIdCounter++;
311
- let id = "_R_" + st.idPrefix + treeId;
312
- if (n > 0)
313
- id += "H" + n.toString(32);
314
- return id + "_";
313
+ const suffix = n > 0 ? "H" + n.toString(32) : "";
314
+ if (REACT_MAJOR < 19) {
315
+ return ":" + st.idPrefix + "R" + treeId + suffix + ":";
316
+ }
317
+ return "_R_" + st.idPrefix + treeId + suffix + "_";
318
+ }
319
+
320
+ // src/slim-react/jsx.ts
321
+ function createElement(type, props, ...children) {
322
+ const normalizedProps = { ...props || {} };
323
+ if (children.length === 1) {
324
+ normalizedProps.children = children[0];
325
+ } else if (children.length > 1) {
326
+ normalizedProps.children = children;
327
+ }
328
+ const key = normalizedProps.key ?? null;
329
+ delete normalizedProps.key;
330
+ return {
331
+ $$typeof: SLIM_ELEMENT,
332
+ type,
333
+ props: normalizedProps,
334
+ key
335
+ };
315
336
  }
316
337
 
317
338
  // src/slim-react/hooks.ts
@@ -364,8 +385,9 @@ function use(usable) {
364
385
  }
365
386
  // src/slim-react/dispatcher.ts
366
387
  import * as ReactNS from "react";
367
- var _reactInternalsKey = "__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE";
368
- var _internals = ReactNS[_reactInternalsKey];
388
+ var _r19 = ReactNS.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
389
+ var _r18Raw = !_r19 ? ReactNS.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED : undefined;
390
+ var _r18 = _r18Raw?.ReactCurrentDispatcher ? _r18Raw : undefined;
369
391
  var slimDispatcher = {
370
392
  useId: makeId,
371
393
  readContext: (ctx) => getContextValue(ctx),
@@ -391,15 +413,23 @@ var slimDispatcher = {
391
413
  useHostTransitionStatus: () => false
392
414
  };
393
415
  function installDispatcher() {
394
- if (!_internals)
395
- return null;
396
- const prev = _internals.H;
397
- _internals.H = slimDispatcher;
398
- return prev;
416
+ if (_r19) {
417
+ const prev = _r19.H;
418
+ _r19.H = slimDispatcher;
419
+ return prev;
420
+ }
421
+ if (_r18) {
422
+ const prev = _r18.ReactCurrentDispatcher.current;
423
+ _r18.ReactCurrentDispatcher.current = slimDispatcher;
424
+ return prev;
425
+ }
426
+ return null;
399
427
  }
400
428
  function restoreDispatcher(prev) {
401
- if (_internals)
402
- _internals.H = prev;
429
+ if (_r19)
430
+ _r19.H = prev;
431
+ else if (_r18)
432
+ _r18.ReactCurrentDispatcher.current = prev;
403
433
  }
404
434
 
405
435
  // src/slim-react/render.ts
@@ -660,7 +690,7 @@ function writeAttributes(writer, props, isSvg, skip) {
660
690
  if (isSvg && key in SVG_ATTR_MAP) {
661
691
  attrName = SVG_ATTR_MAP[key];
662
692
  } else {
663
- attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key;
693
+ attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key === "contentEditable" && REACT_MAJOR < 19 ? "contenteditable" : key;
664
694
  }
665
695
  if (value === false || value == null) {
666
696
  if (value === false && (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-"))) {
@@ -871,7 +901,8 @@ function renderComponent(type, props, writer, isSvg, _suspenseRetries = 0) {
871
901
  const LazyComp = resolved?.default ?? resolved;
872
902
  return renderComponent(LazyComp, props, writer, isSvg);
873
903
  }
874
- if (typeOf === REACT_CONSUMER) {
904
+ const isConsumer = typeOf === REACT_CONSUMER || typeOf === REACT_CONTEXT && "_context" in type && !("value" in props);
905
+ if (isConsumer) {
875
906
  const ctx2 = type._context;
876
907
  const value = ctx2 ? getContextValue(ctx2) : undefined;
877
908
  const result2 = typeof props.children === "function" ? props.children(value) : null;
@@ -2448,6 +2479,20 @@ var HadarsFolder = "./.hadars";
2448
2479
  var StaticPath = `${HadarsFolder}/static`;
2449
2480
  var HADARS_TMP_DIR = pathMod2.join(os.tmpdir(), "hadars");
2450
2481
  var ensureHadarsTmpDir = () => fs.mkdir(HADARS_TMP_DIR, { recursive: true });
2482
+ var readReactMajor = async () => {
2483
+ let dir = process.cwd();
2484
+ while (true) {
2485
+ try {
2486
+ const pkgPath = pathMod2.join(dir, "node_modules", "react", "package.json");
2487
+ const pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8"));
2488
+ return parseInt(pkg.version.split(".")[0], 10);
2489
+ } catch {}
2490
+ const parent = pathMod2.dirname(dir);
2491
+ if (parent === dir)
2492
+ return 19;
2493
+ dir = parent;
2494
+ }
2495
+ };
2451
2496
  var validateOptions = (options) => {
2452
2497
  if (!options.entry) {
2453
2498
  throw new Error("Entry file is required");
@@ -2567,6 +2612,8 @@ var dev = async (options) => {
2567
2612
  });
2568
2613
  const workerCmd = resolveWorkerCmd(packageDir2);
2569
2614
  console.log("Spawning SSR worker:", workerCmd.join(" "), "entry:", entry);
2615
+ const reactMajor = await readReactMajor();
2616
+ const ssrDefine = { __HADARS_REACT_MAJOR__: String(reactMajor), ...options.define };
2570
2617
  const child = spawn(workerCmd[0], [
2571
2618
  ...workerCmd.slice(1),
2572
2619
  `--entry=${entry}`,
@@ -2574,7 +2621,7 @@ var dev = async (options) => {
2574
2621
  `--outFile=${SSR_FILENAME}`,
2575
2622
  `--base=${baseURL}`,
2576
2623
  ...options.swcPlugins ? [`--swcPlugins=${JSON.stringify(options.swcPlugins)}`] : [],
2577
- ...options.define ? [`--define=${JSON.stringify(options.define)}`] : [],
2624
+ `--define=${JSON.stringify(ssrDefine)}`,
2578
2625
  ...options.moduleRules ? [`--moduleRules=${JSON.stringify(options.moduleRules, (_k, v) => v instanceof RegExp ? { __re: v.source, __flags: v.flags } : v)}`] : []
2579
2626
  ], { stdio: "pipe" });
2580
2627
  child.stdin?.end();
@@ -2748,6 +2795,7 @@ var build = async (options) => {
2748
2795
  const tmpFilePath = pathMod2.join(HADARS_TMP_DIR, `client-${Date.now()}.tsx`);
2749
2796
  await fs.writeFile(tmpFilePath, clientScript);
2750
2797
  const resolvedHtmlTemplate = options.htmlTemplate ? await processHtmlTemplate(pathMod2.resolve(__dirname3, options.htmlTemplate)) : undefined;
2798
+ const reactMajor = await readReactMajor();
2751
2799
  console.log("Building client and server bundles in parallel...");
2752
2800
  await Promise.all([
2753
2801
  compileEntry(tmpFilePath, {
@@ -2779,7 +2827,7 @@ var build = async (options) => {
2779
2827
  target: "node",
2780
2828
  mode: "production",
2781
2829
  swcPlugins: options.swcPlugins,
2782
- define: options.define,
2830
+ define: { __HADARS_REACT_MAJOR__: String(reactMajor), ...options.define },
2783
2831
  moduleRules: options.moduleRules,
2784
2832
  plugins: options.plugins,
2785
2833
  postcssPlugins: options.postcssPlugins
@@ -157,25 +157,8 @@ var REACT19_ELEMENT = /* @__PURE__ */ Symbol.for("react.transitional.element");
157
157
  var FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment");
158
158
  var SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense");
159
159
 
160
- // src/slim-react/jsx.ts
161
- function createElement(type, props, ...children) {
162
- const normalizedProps = { ...props || {} };
163
- if (children.length === 1) {
164
- normalizedProps.children = children[0];
165
- } else if (children.length > 1) {
166
- normalizedProps.children = children;
167
- }
168
- const key = normalizedProps.key ?? null;
169
- delete normalizedProps.key;
170
- return {
171
- $$typeof: SLIM_ELEMENT,
172
- type,
173
- props: normalizedProps,
174
- key
175
- };
176
- }
177
-
178
160
  // src/slim-react/renderContext.ts
161
+ var import_node_module = require("module");
179
162
  var MAP_KEY = "__slimReactContextMap";
180
163
  var _g = globalThis;
181
164
  if (!("__slimReactContextMap" in _g)) _g[MAP_KEY] = null;
@@ -197,8 +180,7 @@ function restoreUnsuspend(u) {
197
180
  function getContextValue(context) {
198
181
  const map = _g[MAP_KEY];
199
182
  if (map && map.has(context)) return map.get(context);
200
- const c = context;
201
- return "_defaultValue" in c ? c._defaultValue : c._currentValue;
183
+ return context._currentValue;
202
184
  }
203
185
  function pushContextValue(context, value) {
204
186
  let map = _g[MAP_KEY];
@@ -206,8 +188,7 @@ function pushContextValue(context, value) {
206
188
  map = /* @__PURE__ */ new Map();
207
189
  _g[MAP_KEY] = map;
208
190
  }
209
- const c = context;
210
- const prev = map.has(context) ? map.get(context) : "_defaultValue" in c ? c._defaultValue : c._currentValue;
191
+ const prev = map.has(context) ? map.get(context) : context._currentValue;
211
192
  map.set(context, value);
212
193
  return prev;
213
194
  }
@@ -312,13 +293,58 @@ function getTreeId() {
312
293
  const stripped = (id & ~(1 << 31 - Math.clz32(id))).toString(32);
313
294
  return stripped + overflow;
314
295
  }
296
+ var _detectReact = () => {
297
+ if (typeof __HADARS_REACT_MAJOR__ !== "undefined") {
298
+ const major = parseInt(String(__HADARS_REACT_MAJOR__), 10);
299
+ return {
300
+ major,
301
+ // Exact patch version is unknown from the define alone; use a
302
+ // representative fallback. Most libraries only check the major.
303
+ version: major < 19 ? "18.3.1" : "19.1.1"
304
+ };
305
+ }
306
+ const parse = (ver) => ({ major: parseInt(ver.split(".")[0], 10), version: ver });
307
+ try {
308
+ return parse(require("react").version);
309
+ } catch {
310
+ }
311
+ try {
312
+ const req = (0, import_node_module.createRequire)(process.cwd() + "/__hadars__.js");
313
+ return parse(req("react").version);
314
+ } catch {
315
+ }
316
+ return { major: 19, version: "19.1.1" };
317
+ };
318
+ var _react = _detectReact();
319
+ var REACT_MAJOR = _react.major;
320
+ var REACT_VERSION = _react.version;
315
321
  function makeId() {
316
322
  const st = s();
317
323
  const treeId = getTreeId();
318
324
  const n = st.localIdCounter++;
319
- let id = "_R_" + st.idPrefix + treeId;
320
- if (n > 0) id += "H" + n.toString(32);
321
- return id + "_";
325
+ const suffix = n > 0 ? "H" + n.toString(32) : "";
326
+ if (REACT_MAJOR < 19) {
327
+ return ":" + st.idPrefix + "R" + treeId + suffix + ":";
328
+ }
329
+ return "_R_" + st.idPrefix + treeId + suffix + "_";
330
+ }
331
+
332
+ // src/slim-react/jsx.ts
333
+ function createElement(type, props, ...children) {
334
+ const normalizedProps = { ...props || {} };
335
+ if (children.length === 1) {
336
+ normalizedProps.children = children[0];
337
+ } else if (children.length > 1) {
338
+ normalizedProps.children = children;
339
+ }
340
+ const key = normalizedProps.key ?? null;
341
+ delete normalizedProps.key;
342
+ return {
343
+ $$typeof: SLIM_ELEMENT,
344
+ type,
345
+ props: normalizedProps,
346
+ key
347
+ };
322
348
  }
323
349
 
324
350
  // src/slim-react/hooks.ts
@@ -379,8 +405,9 @@ function use(usable) {
379
405
 
380
406
  // src/slim-react/dispatcher.ts
381
407
  var ReactNS = __toESM(require("react"), 1);
382
- var _reactInternalsKey = "__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE";
383
- var _internals = ReactNS[_reactInternalsKey];
408
+ var _r19 = ReactNS["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
409
+ var _r18Raw = !_r19 ? ReactNS["__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED"] : void 0;
410
+ var _r18 = _r18Raw?.ReactCurrentDispatcher ? _r18Raw : void 0;
384
411
  var slimDispatcher = {
385
412
  useId: makeId,
386
413
  readContext: (ctx) => getContextValue(ctx),
@@ -408,13 +435,21 @@ var slimDispatcher = {
408
435
  useHostTransitionStatus: () => false
409
436
  };
410
437
  function installDispatcher() {
411
- if (!_internals) return null;
412
- const prev = _internals.H;
413
- _internals.H = slimDispatcher;
414
- return prev;
438
+ if (_r19) {
439
+ const prev = _r19.H;
440
+ _r19.H = slimDispatcher;
441
+ return prev;
442
+ }
443
+ if (_r18) {
444
+ const prev = _r18.ReactCurrentDispatcher.current;
445
+ _r18.ReactCurrentDispatcher.current = slimDispatcher;
446
+ return prev;
447
+ }
448
+ return null;
415
449
  }
416
450
  function restoreDispatcher(prev) {
417
- if (_internals) _internals.H = prev;
451
+ if (_r19) _r19.H = prev;
452
+ else if (_r18) _r18.ReactCurrentDispatcher.current = prev;
418
453
  }
419
454
 
420
455
  // src/slim-react/render.ts
@@ -671,7 +706,7 @@ function writeAttributes(writer, props, isSvg, skip) {
671
706
  if (isSvg && key in SVG_ATTR_MAP) {
672
707
  attrName = SVG_ATTR_MAP[key];
673
708
  } else {
674
- attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key;
709
+ attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key === "tabIndex" ? "tabindex" : key === "defaultValue" ? "value" : key === "defaultChecked" ? "checked" : key === "contentEditable" && REACT_MAJOR < 19 ? "contenteditable" : key;
675
710
  }
676
711
  if (value === false || value == null) {
677
712
  if (value === false && (attrName.charCodeAt(0) === 97 && attrName.startsWith("aria-") || attrName.charCodeAt(0) === 100 && attrName.startsWith("data-"))) {
@@ -880,7 +915,8 @@ function renderComponent(type, props, writer, isSvg, _suspenseRetries = 0) {
880
915
  const LazyComp = resolved?.default ?? resolved;
881
916
  return renderComponent(LazyComp, props, writer, isSvg);
882
917
  }
883
- if (typeOf === REACT_CONSUMER) {
918
+ const isConsumer = typeOf === REACT_CONSUMER || typeOf === REACT_CONTEXT && "_context" in type && !("value" in props);
919
+ if (isConsumer) {
884
920
  const ctx2 = type._context;
885
921
  const value = ctx2 ? getContextValue(ctx2) : void 0;
886
922
  const result2 = typeof props.children === "function" ? props.children(value) : null;
@@ -6,9 +6,10 @@ import {
6
6
  getReactResponse,
7
7
  makePrecontentHtmlGetter,
8
8
  parseRequest
9
- } from "./chunk-NYLXE7T7.js";
10
- import "./chunk-2TMQUXFL.js";
9
+ } from "./chunk-U2JQR4HV.js";
10
+ import "./chunk-HIKMDNRB.js";
11
11
  import "./chunk-OZUZS2PD.js";
12
+ import "./chunk-3RG5ZIWI.js";
12
13
 
13
14
  // src/cloudflare.ts
14
15
  import "react";