Skip to content

Commit 4cbb042

Browse files
refactor(runtime-core): extract load entry error recovery helper
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 55ed3ab commit 4cbb042

File tree

1 file changed

+50
-26
lines changed
  • packages/runtime-core/src/utils

1 file changed

+50
-26
lines changed

packages/runtime-core/src/utils/load.ts

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,42 @@ export async function getRemoteEntry(params: {
274274
return singleFlight(globalLoading, uniqueKey, () => {
275275
const loadEntryHook = origin.remoteHandler.hooks.lifecycle.loadEntry;
276276
const loaderHook = origin.loaderHook;
277+
const markLoadEntryError = (error: Error) => {
278+
(error as Error & { __mfLoadEntryError?: true }).__mfLoadEntryError =
279+
true;
280+
return error;
281+
};
282+
const recoverFromLoadEntryError = (
283+
resourceUrl: string | undefined,
284+
remoteName: string,
285+
) =>
286+
Effect.tryPromise({
287+
try: async () => {
288+
if (!_inErrorHandling) {
289+
const recovered =
290+
await origin.loaderHook.lifecycle.loadEntryError.emit({
291+
getRemoteEntry: (p) =>
292+
getRemoteEntry({ ...p, _inErrorHandling: true }),
293+
origin,
294+
remoteInfo,
295+
remoteEntryExports,
296+
globalLoading,
297+
uniqueKey,
298+
});
299+
if (recovered)
300+
return recovered as RemoteEntryExports | void | undefined;
301+
}
302+
throw markLoadEntryError(
303+
new Error(
304+
runtimeError(RUNTIME_008, {
305+
remoteName,
306+
resourceUrl,
307+
}),
308+
),
309+
);
310+
},
311+
catch: (e) => e as Error,
312+
});
277313
// Run the Effect program, bridging back to Promise for the globalLoading cache
278314
const effectProgram = getRemoteEntryEffect({
279315
origin,
@@ -284,33 +320,21 @@ export async function getRemoteEntry(params: {
284320
getEntryUrl,
285321
}).pipe(
286322
Effect.catchTag('ScriptLoadFailed', (err) =>
287-
Effect.tryPromise({
288-
try: async () => {
289-
if (err.resourceUrl !== undefined && !_inErrorHandling) {
290-
const recovered =
291-
await origin.loaderHook.lifecycle.loadEntryError.emit({
292-
getRemoteEntry: (p) =>
293-
getRemoteEntry({ ...p, _inErrorHandling: true }),
294-
origin,
295-
remoteInfo,
296-
remoteEntryExports,
297-
globalLoading,
298-
uniqueKey,
299-
});
300-
if (recovered)
301-
return recovered as RemoteEntryExports | void | undefined;
302-
}
303-
throw new Error(
304-
runtimeError(RUNTIME_008, {
305-
remoteName: err.remoteName,
306-
resourceUrl: err.resourceUrl,
307-
}),
308-
);
309-
},
310-
catch: (e) => e as Error,
311-
}),
323+
recoverFromLoadEntryError(err.resourceUrl, err.remoteName),
312324
),
313-
Effect.catch((err) => Effect.fail(err as Error)),
325+
Effect.catch((err) => {
326+
if (
327+
!(err as any)?.__mfLoadEntryError &&
328+
err instanceof Error &&
329+
err.message.includes(RUNTIME_008)
330+
) {
331+
return recoverFromLoadEntryError(
332+
getEntryUrl ? getEntryUrl(remoteInfo.entry) : remoteInfo.entry,
333+
remoteInfo.name,
334+
);
335+
}
336+
return Effect.fail(err as Error);
337+
}),
314338
);
315339
return Effect.runPromise(effectProgram).catch((err) => {
316340
throw err;

0 commit comments

Comments
 (0)