fix(platform): preserve session failures and URL syntax

This commit is contained in:
2026-09-05 06:38:00 +08:00
parent 7e5a950cc7
commit 224df1c21c
6 changed files with 123 additions and 8 deletions
@@ -16,6 +16,16 @@ export type GameSessionState =
| 'disposing'
| 'disposed';
export class GameSessionOpenFault extends Error {
readonly errors: readonly unknown[];
constructor(primary: unknown, cleanup: unknown) {
super('Game session open failed and module cleanup also failed');
this.name = 'GameSessionOpenFault';
this.errors = Object.freeze([primary, cleanup]);
}
}
/** Validates the compile-time game identity before it reaches the runtime. */
export function assertGameEntry(entry: GameEntry): void {
assertNonEmptyText(entry.key, 'key');
@@ -38,7 +48,7 @@ export function assertGameEntry(entry: GameEntry): void {
try {
assertGameModule(module);
} finally {
disposeValidationModule(module);
disposeModuleIfPresent(module);
}
}
@@ -71,14 +81,20 @@ export class GameSessionHost {
this.module = module;
module.attach(host);
this.currentState = 'active';
} catch (error) {
} catch (primaryError) {
this.module = undefined;
let cleanupFailed = false;
let cleanupError: unknown;
try {
module?.dispose();
disposeModuleIfPresent(module);
} catch (error) {
cleanupFailed = true;
cleanupError = error;
} finally {
this.currentState = 'idle';
}
throw error;
if (cleanupFailed) throw new GameSessionOpenFault(primaryError, cleanupError);
throw primaryError;
}
}
@@ -174,7 +190,7 @@ function assertGameModule(module: unknown): asserts module is GameModule {
}
}
function disposeValidationModule(module: unknown): void {
function disposeModuleIfPresent(module: unknown): void {
if (!module || typeof module !== 'object') return;
const dispose = (module as Record<string, unknown>).dispose;
if (typeof dispose === 'function') dispose.call(module);