@absolutejs/absolute 0.20.0-beta.122 → 0.20.0-beta.123

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/CHANGELOG.md CHANGED
@@ -6,6 +6,28 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.20.0-beta.123 — 2026-09-28
10
+
11
+ ### Added
12
+
13
+ - **React Fast Refresh keeps component state: `absolute dev` can run on AbsoluteJS's patched Bun**
14
+ Stock Bun ignores `reactFastRefresh` on `Bun.Transpiler` (oven-sh/bun#32919), so React edits in `absolute dev` remounted the page and lost component state. AbsoluteJS now publishes Bun 1.4.0 with just that fix for every platform Bun ships (github.com/absolutejs/patched-bun). In React projects on stock Bun, `absolute dev` offers it once (Install now / Ask me later / Don't ask again); it installs to ~/.absolutejs/bun, is checked against a pinned SHA-256, and only the dev server uses it, so your `bun` is unchanged. `absolute bun-patch [status|install|remove|reset]` manages it; `ABSOLUTE_PATCHED_BUN=0` opts out.
15
+
16
+ ### Fixed
17
+
18
+ - **`absolute dev` keeps rebuilding after a syntax error in a React component or an unhandled rejection**
19
+ Under `bun --hot`, Bun counts unhandled rejections that no listener claims and never resets the count; while it is non-zero Bun parks the process in a loop that still serves requests and delivers file-watch events but never runs timers. The server entry imports React pages, so saving a React component with a syntax error made Bun's hot reload reject, and from then on the HMR debounce never fired: every edit was detected and queued, including the one that fixed the error, and nothing rebuilt until the dev server restarted. An unhandled rejection in app code did the same. The dev server now claims unhandled rejections and prints them as before, so its timers keep running.
20
+ - **The patched Bun is now a release build, not a canary build**
21
+ `absolute bun-patch install` and the `absolute dev` offer now install `bun-v1.4.0-absolute.2`. The first release was built as a Bun canary build (Bun's build default): it reported `1.4.0-canary.1`, enabled Bun's experimental "bake" server features and made `bun upgrade` track canary. absolute.2 is built with `--canary=off`, as Bun's own releases are; the React Fast Refresh fix is unchanged. Run `absolute bun-patch install` to replace an absolute.1 install.
22
+ - **Removed a React HMR CSS branch that only matched the example app**
23
+ The React HMR client had a CSS-only branch that looked up the example app's `ReactExampleCSS` manifest key, so it could never work in another app; the server never sends a CSS-only React update, so it was also unreachable. Removed. Stylesheet edits on React pages go through the general stylesheet swap, now covered by a browser test (the rule applies, component state and the document are kept).
24
+ - **React edits that add a component, touch a hook or utility, or create a folder now update the page in place**
25
+ The React fast path told the browser to re-import a single module: the first non-page file in the batch. A new component added to the page re-imported only the new file, so the page never rendered it; a folder created alongside a file became the target and its URL failed to load; and an edited hook or utility whose importer had not been fetched through the module server re-imported just itself, which updates nothing on screen. Every edited file now gets a target (hooks and utilities resolve to the nearest importing component, falling back to the dependents the dependency graph found), directories and deleted paths are skipped, and the client imports them all before refreshing. On stock Bun the remount fallback rendered the changed child in place of the whole page; it now re-imports the page module for the page on screen and ignores edits that do not reach it.
26
+ - **React Fast Refresh is used when Bun supports it, instead of always falling back to a remount**
27
+ The dev server decides between React Fast Refresh and the stock-Bun remount fallback by transpiling a probe component. The probe was named `__AbsoluteRefreshProbe`; React Fast Refresh registers only capitalized components, so it reported "unsupported" even on a Bun with the reactFastRefresh fix, and React edits always remounted with a warning. It now uses a capitalized name.
28
+ - **A syntax error in a React component shows the error overlay instead of reloading the page**
29
+ A React edit that failed to compile was still broadcast as an update. The browser imported a module that answered 500 and fell back to a full reload, which showed the last good page and no error. The dev server now checks the edited modules compile first and sends the error overlay (file, line and source line) instead; the save that fixes it applies as a normal in-place update. The module server handler and its transform errors also moved to globalThis: after a `bun --hot` reload failed part-way, later imports of the module server got a fresh instance that was never configured, so pre-transforming the changed module silently did nothing.
30
+
9
31
  ## 0.20.0-beta.122 — 2026-09-27
10
32
 
11
33
  ### Fixed
package/changelog.json CHANGED
@@ -2,6 +2,47 @@
2
2
  "contract": 1,
3
3
  "name": "@absolutejs/absolute",
4
4
  "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "detail": "Under `bun --hot`, Bun counts unhandled rejections that no listener claims and never resets the count; while it is non-zero Bun parks the process in a loop that still serves requests and delivers file-watch events but never runs timers. The server entry imports React pages, so saving a React component with a syntax error made Bun's hot reload reject, and from then on the HMR debounce never fired: every edit was detected and queued, including the one that fixed the error, and nothing rebuilt until the dev server restarted. An unhandled rejection in app code did the same. The dev server now claims unhandled rejections and prints them as before, so its timers keep running.",
9
+ "kind": "fixed",
10
+ "summary": "`absolute dev` keeps rebuilding after a syntax error in a React component or an unhandled rejection"
11
+ },
12
+ {
13
+ "detail": "`absolute bun-patch install` and the `absolute dev` offer now install `bun-v1.4.0-absolute.2`. The first release was built as a Bun canary build (Bun's build default): it reported `1.4.0-canary.1`, enabled Bun's experimental \"bake\" server features and made `bun upgrade` track canary. absolute.2 is built with `--canary=off`, as Bun's own releases are; the React Fast Refresh fix is unchanged. Run `absolute bun-patch install` to replace an absolute.1 install.",
14
+ "kind": "fixed",
15
+ "summary": "The patched Bun is now a release build, not a canary build"
16
+ },
17
+ {
18
+ "detail": "Stock Bun ignores `reactFastRefresh` on `Bun.Transpiler` (oven-sh/bun#32919), so React edits in `absolute dev` remounted the page and lost component state. AbsoluteJS now publishes Bun 1.4.0 with just that fix for every platform Bun ships (github.com/absolutejs/patched-bun). In React projects on stock Bun, `absolute dev` offers it once (Install now / Ask me later / Don't ask again); it installs to ~/.absolutejs/bun, is checked against a pinned SHA-256, and only the dev server uses it, so your `bun` is unchanged. `absolute bun-patch [status|install|remove|reset]` manages it; `ABSOLUTE_PATCHED_BUN=0` opts out.",
19
+ "kind": "added",
20
+ "summary": "React Fast Refresh keeps component state: `absolute dev` can run on AbsoluteJS's patched Bun"
21
+ },
22
+ {
23
+ "detail": "The React HMR client had a CSS-only branch that looked up the example app's `ReactExampleCSS` manifest key, so it could never work in another app; the server never sends a CSS-only React update, so it was also unreachable. Removed. Stylesheet edits on React pages go through the general stylesheet swap, now covered by a browser test (the rule applies, component state and the document are kept).",
24
+ "kind": "fixed",
25
+ "summary": "Removed a React HMR CSS branch that only matched the example app"
26
+ },
27
+ {
28
+ "detail": "The React fast path told the browser to re-import a single module: the first non-page file in the batch. A new component added to the page re-imported only the new file, so the page never rendered it; a folder created alongside a file became the target and its URL failed to load; and an edited hook or utility whose importer had not been fetched through the module server re-imported just itself, which updates nothing on screen. Every edited file now gets a target (hooks and utilities resolve to the nearest importing component, falling back to the dependents the dependency graph found), directories and deleted paths are skipped, and the client imports them all before refreshing. On stock Bun the remount fallback rendered the changed child in place of the whole page; it now re-imports the page module for the page on screen and ignores edits that do not reach it.",
29
+ "kind": "fixed",
30
+ "summary": "React edits that add a component, touch a hook or utility, or create a folder now update the page in place"
31
+ },
32
+ {
33
+ "detail": "The dev server decides between React Fast Refresh and the stock-Bun remount fallback by transpiling a probe component. The probe was named `__AbsoluteRefreshProbe`; React Fast Refresh registers only capitalized components, so it reported \"unsupported\" even on a Bun with the reactFastRefresh fix, and React edits always remounted with a warning. It now uses a capitalized name.",
34
+ "kind": "fixed",
35
+ "summary": "React Fast Refresh is used when Bun supports it, instead of always falling back to a remount"
36
+ },
37
+ {
38
+ "detail": "A React edit that failed to compile was still broadcast as an update. The browser imported a module that answered 500 and fell back to a full reload, which showed the last good page and no error. The dev server now checks the edited modules compile first and sends the error overlay (file, line and source line) instead; the save that fixes it applies as a normal in-place update. The module server handler and its transform errors also moved to globalThis: after a `bun --hot` reload failed part-way, later imports of the module server got a fresh instance that was never configured, so pre-transforming the changed module silently did nothing.",
39
+ "kind": "fixed",
40
+ "summary": "A syntax error in a React component shows the error overlay instead of reloading the page"
41
+ }
42
+ ],
43
+ "date": "2026-09-28",
44
+ "version": "0.20.0-beta.123"
45
+ },
5
46
  {
6
47
  "changes": [
7
48
  {
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-LiuoUM/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-TZvQHy/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-LiuoUM/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-TZvQHy/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
48
48
  getWarningController()?.maybeWarn(primitiveName);
49
49
  };
50
50
 
51
- // .angular-partial-tmp-LiuoUM/src/core/streamingSlotRegistry.ts
51
+ // .angular-partial-tmp-TZvQHy/src/core/streamingSlotRegistry.ts
52
52
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
53
53
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
54
54
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
package/dist/build.js CHANGED
@@ -21873,7 +21873,7 @@ var init_compileAngular = __esm(() => {
21873
21873
 
21874
21874
  // node_modules/content-tag/pkg/node/content_tag.cjs
21875
21875
  var require_content_tag = __commonJS(function(exports, module) {
21876
- var __dirname = "/tmp/abs-translation-fix/node_modules/content-tag/pkg/node";
21876
+ var __dirname = "/home/alexkahn/abs/absolutejs/.claude/worktrees/release/node_modules/content-tag/pkg/node";
21877
21877
  var imports = {};
21878
21878
  imports["__wbindgen_placeholder__"] = exports;
21879
21879
  var wasm;
@@ -26173,15 +26173,6 @@ var init_fileHashTracker = __esm(() => {
26173
26173
  });
26174
26174
 
26175
26175
  // src/dev/transformCache.ts
26176
- var exports_transformCache = {};
26177
- __export(exports_transformCache, {
26178
- findNearestComponent: () => findNearestComponent,
26179
- getInvalidationVersion: () => getInvalidationVersion,
26180
- getTransformed: () => getTransformed,
26181
- invalidate: () => invalidate,
26182
- invalidateAll: () => invalidateAll,
26183
- setTransformed: () => setTransformed
26184
- });
26185
26176
  var cache, importers, getTransformed = (filePath) => cache.get(filePath)?.content, setTransformed = (filePath, content, mtime, imports) => {
26186
26177
  const resolvedImports = imports ?? [];
26187
26178
  cache.set(filePath, { content, imports: resolvedImports, mtime });
@@ -26233,10 +26224,6 @@ var cache, importers, getTransformed = (filePath) => cache.get(filePath)?.conten
26233
26224
  queue.push(parent);
26234
26225
  }
26235
26226
  }
26236
- }, invalidateAll = () => {
26237
- cache.clear();
26238
- importers.clear();
26239
- invalidationVersions.clear();
26240
26227
  };
26241
26228
  var init_transformCache = __esm(() => {
26242
26229
  cache = globalThis.__transformCache ?? new Map;
@@ -33053,6 +33040,7 @@ __export(exports_moduleServer, {
33053
33040
  SRC_URL_PREFIX: () => SRC_URL_PREFIX2,
33054
33041
  createDevPageWarmer: () => createDevPageWarmer,
33055
33042
  createModuleServer: () => createModuleServer,
33043
+ getTransformError: () => getTransformError,
33056
33044
  importedBindingNames: () => importedBindingNames,
33057
33045
  invalidateModule: () => invalidateModule,
33058
33046
  isReactFastRefreshSupported: () => isReactFastRefreshSupported,
@@ -33253,7 +33241,7 @@ ${code2}`;
33253
33241
  reactFastRefresh: true
33254
33242
  };
33255
33243
  const probe = new Bun.Transpiler(probeOptions);
33256
- const out = probe.transformSync("export function __AbsoluteRefreshProbe(){return null;}");
33244
+ const out = probe.transformSync("export function AbsoluteRefreshProbe(){return null;}");
33257
33245
  return out.includes("$RefreshReg$");
33258
33246
  } catch {
33259
33247
  return false;
@@ -33262,7 +33250,7 @@ ${code2}`;
33262
33250
  if (reactFastRefreshSupported || reactFastRefreshWarningEmitted)
33263
33251
  return;
33264
33252
  reactFastRefreshWarningEmitted = true;
33265
- logWarn("React HMR is blocked: this Bun build ignores " + "`reactFastRefresh` on Bun.Transpiler, so component state " + "cannot be preserved across edits. Tracking " + "https://github.com/oven-sh/bun/pull/28312 \u2014 if it still has " + "not merged, leave a \uD83D\uDC4D on the PR so the Bun team knows it " + "is blocking you. Until then, React edits trigger a targeted " + "page remount instead of a state-preserving fast refresh.");
33253
+ logWarn("React edits remount the page instead of keeping component state: " + "this Bun ignores `reactFastRefresh` on Bun.Transpiler " + "(https://github.com/oven-sh/bun/issues/32919). Run " + "`absolute bun-patch install` to use AbsoluteJS's patched Bun, " + "which has the fix; `absolute dev` then uses it automatically.");
33266
33254
  }, transformReactFile = (filePath, projectRoot, rewriter) => {
33267
33255
  const raw = readFileSync40(filePath, "utf-8");
33268
33256
  const valueExports = tsxTranspiler.scan(raw).exports;
@@ -33812,7 +33800,27 @@ export default {};
33812
33800
  const content = await transformVueFile(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
33813
33801
  setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
33814
33802
  return jsResponse(content);
33815
- }, transformErrorResponse = (err) => {
33803
+ }, transformErrors, readPosition = (value) => {
33804
+ if (!value || typeof value !== "object")
33805
+ return;
33806
+ const position = Reflect.get(value, "position");
33807
+ if (!position || typeof position !== "object")
33808
+ return;
33809
+ const line = Reflect.get(position, "line");
33810
+ const column = Reflect.get(position, "column");
33811
+ const lineText = Reflect.get(position, "lineText");
33812
+ return {
33813
+ column: typeof column === "number" ? column : undefined,
33814
+ line: typeof line === "number" ? line : undefined,
33815
+ lineText: typeof lineText === "string" ? lineText : undefined
33816
+ };
33817
+ }, describeTransformError = (err) => {
33818
+ const [first] = err instanceof AggregateError && Array.isArray(err.errors) ? err.errors : [err];
33819
+ const source = first ?? err;
33820
+ const ownMessage = source && typeof source === "object" ? Reflect.get(source, "message") : undefined;
33821
+ const message = typeof ownMessage === "string" ? ownMessage : String(source);
33822
+ return { message, ...readPosition(first) };
33823
+ }, getTransformError = (filePath) => transformErrors.get(resolve51(filePath)), transformErrorResponse = (err) => {
33816
33824
  const errMsg = err instanceof Error ? err.message : String(err);
33817
33825
  return new Response(`console.error('[ModuleServer] Transform error:', ${JSON.stringify(errMsg)});`, {
33818
33826
  headers: { "Content-Type": "application/javascript" },
@@ -33840,8 +33848,11 @@ export default {};
33840
33848
  return virtualCssResponse;
33841
33849
  const { filePath, ext } = resolveSourcePath2(relPath, projectRoot);
33842
33850
  try {
33843
- return await transformAndCache(filePath, ext, projectRoot, rewriter, frameworkDirs?.vue, stylePreprocessors);
33851
+ const response = await transformAndCache(filePath, ext, projectRoot, rewriter, frameworkDirs?.vue, stylePreprocessors);
33852
+ transformErrors.delete(resolve51(filePath));
33853
+ return response;
33844
33854
  } catch (err) {
33855
+ transformErrors.set(resolve51(filePath), describeTransformError(err));
33845
33856
  return transformErrorResponse(err);
33846
33857
  }
33847
33858
  };
@@ -33854,21 +33865,23 @@ export default {};
33854
33865
  files.push(resolve51(projectRoot, match[1]));
33855
33866
  }
33856
33867
  return files;
33857
- }, invalidateModule = (filePath) => {
33868
+ }, SRC_URL_PREFIX2, invalidateModule = (filePath) => {
33858
33869
  const resolved = resolve51(filePath);
33870
+ transformErrors.delete(resolved);
33859
33871
  invalidate(filePath);
33860
33872
  if (resolved !== filePath)
33861
33873
  invalidate(resolved);
33862
33874
  mtimeCache.delete(filePath);
33863
33875
  mtimeCache.delete(resolved);
33876
+ }, setGlobalModuleServer = (handler) => {
33877
+ globalThis.__absoluteModuleServer = handler ?? undefined;
33864
33878
  }, warmCache = async (pathname) => {
33865
33879
  if (!pathname.startsWith(SRC_PREFIX))
33866
33880
  return;
33867
- if (!globalModuleServer)
33881
+ const handler = globalThis.__absoluteModuleServer;
33882
+ if (!handler)
33868
33883
  return;
33869
- await globalModuleServer(pathname);
33870
- }, globalModuleServer = null, SRC_URL_PREFIX2, setGlobalModuleServer = (handler) => {
33871
- globalModuleServer = handler;
33884
+ await handler(pathname);
33872
33885
  }, REBUILD_IDLE_POLL_MS = 10, getDevResult = () => globalThis.__hmrDevResult, resolveDevPageEntry = (keyOrPath) => {
33873
33886
  const cached = getDevResult();
33874
33887
  const lazy = cached?.hmrState.lazyPages;
@@ -34039,6 +34052,8 @@ export function __legacyDecorateParamTS(paramIndex, decorator) {
34039
34052
  return function (target, key) { decorator(target, key, paramIndex); };
34040
34053
  }
34041
34054
  `.trim();
34055
+ transformErrors = globalThis.__absoluteTransformErrors ?? new Map;
34056
+ globalThis.__absoluteTransformErrors = transformErrors;
34042
34057
  SRC_IMPORT_RE = /\/@src\/([^"'?\s]+)/g;
34043
34058
  SRC_URL_PREFIX2 = SRC_PREFIX;
34044
34059
  });
@@ -34343,7 +34358,7 @@ __export(exports_rebuildTrigger, {
34343
34358
  queueFileChange: () => queueFileChange,
34344
34359
  triggerRebuild: () => triggerRebuild
34345
34360
  });
34346
- import { existsSync as existsSync47, readdirSync as readdirSync13, rmSync as rmSync4 } from "fs";
34361
+ import { existsSync as existsSync47, readdirSync as readdirSync13, rmSync as rmSync4, statSync as statSync8 } from "fs";
34347
34362
  import {
34348
34363
  basename as basename21,
34349
34364
  dirname as dirname36,
@@ -35488,28 +35503,76 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
35488
35503
  const url = `${SRC_URL_PREFIX3}${rel}`;
35489
35504
  await warmCache2(url);
35490
35505
  return url;
35491
- }, getReactModuleUrl, resolveBroadcastTarget = async (primaryFile) => {
35492
- const isComponentFile2 = primaryFile.endsWith(".tsx") || primaryFile.endsWith(".jsx");
35493
- if (isComponentFile2)
35494
- return primaryFile;
35495
- const { findNearestComponent: findNearestComponent2 } = await Promise.resolve().then(() => (init_transformCache(), exports_transformCache));
35496
- const nearest = findNearestComponent2(resolvePath4(primaryFile));
35497
- return nearest ?? primaryFile;
35506
+ }, getReactModuleUrl, isReactComponentPath = (file5) => file5.endsWith(".tsx") || file5.endsWith(".jsx"), isReactPagePath = (file5) => file5.replace(/\\/g, "/").includes("/pages/"), isImportableModule = (file5) => {
35507
+ try {
35508
+ return statSync8(file5).isFile();
35509
+ } catch {
35510
+ return false;
35511
+ }
35512
+ }, resolveComponentTarget = (file5, reactFiles, edited) => {
35513
+ if (isReactComponentPath(file5))
35514
+ return file5;
35515
+ const nearest = findNearestComponent(resolvePath4(file5));
35516
+ if (nearest && isImportableModule(nearest))
35517
+ return nearest;
35518
+ const dependents = reactFiles.filter((candidate) => !edited.has(candidate) && isReactComponentPath(candidate) && isImportableModule(candidate));
35519
+ return dependents.find((candidate) => !isReactPagePath(candidate)) ?? dependents[0] ?? file5;
35520
+ }, resolveReactUpdateTargets = (state, reactFiles) => {
35521
+ const importable = reactFiles.filter(isImportableModule);
35522
+ const userEdited = importable.filter((file5) => state.lastUserEditedFiles?.has(resolvePath4(file5)));
35523
+ const editedFiles = userEdited.length > 0 ? userEdited : importable;
35524
+ const edited = new Set(editedFiles);
35525
+ const ordered = [
35526
+ ...editedFiles.filter((file5) => !isReactPagePath(file5)),
35527
+ ...editedFiles.filter(isReactPagePath)
35528
+ ];
35529
+ const targets = ordered.map((file5) => resolveComponentTarget(file5, reactFiles, edited));
35530
+ return { editedFiles, targets: [...new Set(targets)] };
35531
+ }, resolveAffectedPageModules = async (reactFiles) => {
35532
+ const pages = reactFiles.filter((file5) => isReactPagePath(file5) && isReactComponentPath(file5) && isImportableModule(file5));
35533
+ const entries = await Promise.all(pages.map(async (page) => [
35534
+ `${basename21(page).replace(/\.[jt]sx$/, "")}Index`,
35535
+ await getReactModuleUrl(page)
35536
+ ]));
35537
+ return Object.fromEntries(entries);
35498
35538
  }, handleReactModuleServerPath = async (state, reactFiles, startTime, fastRefreshSupported, onRebuildComplete) => {
35499
- const primaryFile = reactFiles.find((file5) => !file5.replace(/\\/g, "/").includes("/pages/")) ?? reactFiles[0];
35500
- if (!primaryFile) {
35539
+ const { invalidateModule: invalidateModule2 } = await getModuleServer();
35540
+ for (const file5 of reactFiles) {
35541
+ invalidateModule2(file5);
35542
+ }
35543
+ const { editedFiles, targets } = resolveReactUpdateTargets(state, reactFiles);
35544
+ const [primaryTarget] = targets;
35545
+ if (!primaryTarget) {
35501
35546
  onRebuildComplete({
35502
35547
  hmrState: state,
35503
35548
  manifest: state.manifest
35504
35549
  });
35505
35550
  return state.manifest;
35506
35551
  }
35507
- const { invalidateModule: invalidateModule2 } = await getModuleServer();
35508
- for (const file5 of reactFiles) {
35509
- invalidateModule2(file5);
35552
+ const moduleUrls = await Promise.all(targets.map(getReactModuleUrl));
35553
+ await Promise.all(editedFiles.filter((file5) => !targets.includes(file5)).map(getReactModuleUrl));
35554
+ const { getTransformError: getTransformError2 } = await getModuleServer();
35555
+ const failed = [...new Set([...editedFiles, ...targets])].map((file5) => ({ error: getTransformError2(file5), file: file5 })).find((entry) => entry.error !== undefined);
35556
+ if (failed?.error) {
35557
+ broadcastToClients(state, {
35558
+ data: {
35559
+ affectedFrameworks: ["react"],
35560
+ column: failed.error.column,
35561
+ error: failed.error.message,
35562
+ file: failed.file,
35563
+ framework: "react",
35564
+ line: failed.error.line,
35565
+ lineText: failed.error.lineText
35566
+ },
35567
+ message: "React module failed to compile",
35568
+ type: "rebuild-error"
35569
+ });
35570
+ onRebuildComplete({ hmrState: state, manifest: state.manifest });
35571
+ return state.manifest;
35510
35572
  }
35511
- const broadcastTarget = await resolveBroadcastTarget(primaryFile);
35512
- const pageModuleUrl = await getReactModuleUrl(broadcastTarget);
35573
+ const pageModuleUrls = fastRefreshSupported ? undefined : await resolveAffectedPageModules(reactFiles);
35574
+ const [pageModuleUrl] = moduleUrls;
35575
+ const primaryFile = reactFiles.find((file5) => isImportableModule(file5) && !isReactPagePath(file5)) ?? primaryTarget;
35513
35576
  if (pageModuleUrl) {
35514
35577
  const serverDuration = Date.now() - startTime;
35515
35578
  state.lastHmrPath = relative24(process.cwd(), primaryFile).replace(/\\/g, "/");
@@ -35521,7 +35584,9 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
35521
35584
  hasComponentChanges: true,
35522
35585
  hasCSSChanges: false,
35523
35586
  manifest: state.manifest,
35587
+ moduleUrls,
35524
35588
  pageModuleUrl,
35589
+ pageModuleUrls,
35525
35590
  primarySource: primaryFile,
35526
35591
  serverDuration,
35527
35592
  sourceFiles: reactFiles
@@ -37532,7 +37597,7 @@ __export(exports_devBuild, {
37532
37597
  devBuild: () => devBuild
37533
37598
  });
37534
37599
  import { readdir as readdir6 } from "fs/promises";
37535
- import { existsSync as existsSync49, statSync as statSync8 } from "fs";
37600
+ import { existsSync as existsSync49, statSync as statSync9 } from "fs";
37536
37601
  import { resolve as resolve55 } from "path";
37537
37602
  var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve55(import.meta.dir, "../dev/client"), collectDepVendorSourceDirs = (config) => {
37538
37603
  const configuredDirs = [
@@ -37672,7 +37737,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve55(import.meta.d
37672
37737
  });
37673
37738
  }
37674
37739
  }, handleCachedReload = async () => {
37675
- const serverMtime = statSync8(resolve55(Bun.main)).mtimeMs;
37740
+ const serverMtime = statSync9(resolve55(Bun.main)).mtimeMs;
37676
37741
  const lastMtime = globalThis.__hmrServerMtime;
37677
37742
  globalThis.__hmrServerMtime = serverMtime;
37678
37743
  const cached = globalThis.__hmrDevResult;
@@ -38053,7 +38118,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve55(import.meta.d
38053
38118
  manifest
38054
38119
  };
38055
38120
  globalThis.__hmrDevResult = result;
38056
- globalThis.__hmrServerMtime = statSync8(resolve55(Bun.main)).mtimeMs;
38121
+ globalThis.__hmrServerMtime = statSync9(resolve55(Bun.main)).mtimeMs;
38057
38122
  return result;
38058
38123
  };
38059
38124
  var init_devBuild = __esm(() => {
@@ -38094,5 +38159,5 @@ export {
38094
38159
  devBuild
38095
38160
  };
38096
38161
 
38097
- //# debugId=F8C17F2264022D4D64756E2164756E21
38162
+ //# debugId=71208AEC5F61453764756E2164756E21
38098
38163
  //# sourceMappingURL=build.js.map