fix(platform): recognize session faults across realms
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'node:test';
|
||||
import { runInNewContext } from 'node:vm';
|
||||
import type {
|
||||
GameEntry,
|
||||
GameHost,
|
||||
@@ -11,7 +12,11 @@ import type {
|
||||
import {
|
||||
assertGameEntry,
|
||||
GameSessionHost,
|
||||
GameSessionOpenFault,
|
||||
} from '../../YouleNexus/assets/framework/sdk/runtime/game-session-host.ts';
|
||||
import * as gameSessionRuntime from '../../YouleNexus/assets/framework/sdk/runtime/game-session-host.ts';
|
||||
|
||||
const OPEN_FAULT_BRAND_KEY = 'youle.framework.sdk.GameSessionOpenFault';
|
||||
|
||||
function makeHost(): GameHost {
|
||||
const snapshot: PlatformGameSnapshot = {
|
||||
@@ -221,6 +226,61 @@ test('GameSessionHost preserves attach then dispose failures by identity and occ
|
||||
assert.equal(sessions.state, 'idle');
|
||||
});
|
||||
|
||||
test('open fault guard recognizes the global brand across realms without reading accessors', () => {
|
||||
type OpenFaultShape = { readonly errors: readonly unknown[] };
|
||||
type OpenFaultGuard = (value: unknown) => value is OpenFaultShape;
|
||||
const exported = (gameSessionRuntime as unknown as Record<string, unknown>)
|
||||
.isGameSessionOpenFault;
|
||||
assert.equal(typeof exported, 'function');
|
||||
const isGameSessionOpenFault = exported as OpenFaultGuard;
|
||||
const primary = new Error('primary');
|
||||
const cleanup = new Error('cleanup');
|
||||
const sameRealm = new GameSessionOpenFault(primary, cleanup);
|
||||
const foreignRealm = runInNewContext(`(() => {
|
||||
const fault = new Error('foreign open fault');
|
||||
Object.defineProperties(fault, {
|
||||
[Symbol.for(${JSON.stringify(OPEN_FAULT_BRAND_KEY)})]: { value: true },
|
||||
errors: { value: [primary, cleanup] },
|
||||
});
|
||||
return fault;
|
||||
})()`, { primary, cleanup });
|
||||
const ordinaryAggregate = runInNewContext(
|
||||
'new AggregateError([primary, cleanup], "user aggregate")',
|
||||
{ primary, cleanup },
|
||||
);
|
||||
const unbranded = { errors: [primary, cleanup] };
|
||||
let accessorReads = 0;
|
||||
const accessorSpoof = new Error('accessor spoof');
|
||||
Object.defineProperties(accessorSpoof, {
|
||||
[Symbol.for(OPEN_FAULT_BRAND_KEY)]: { value: true },
|
||||
errors: {
|
||||
get() {
|
||||
accessorReads += 1;
|
||||
throw new Error('errors getter must not run');
|
||||
},
|
||||
},
|
||||
});
|
||||
const brandAccessorSpoof = new Error('brand accessor spoof');
|
||||
Object.defineProperties(brandAccessorSpoof, {
|
||||
[Symbol.for(OPEN_FAULT_BRAND_KEY)]: {
|
||||
get() {
|
||||
accessorReads += 1;
|
||||
throw new Error('brand getter must not run');
|
||||
},
|
||||
},
|
||||
errors: { value: [primary, cleanup] },
|
||||
});
|
||||
|
||||
assert.equal(foreignRealm instanceof GameSessionOpenFault, false);
|
||||
assert.equal(isGameSessionOpenFault(sameRealm), true);
|
||||
assert.equal(isGameSessionOpenFault(foreignRealm), true);
|
||||
assert.equal(isGameSessionOpenFault(ordinaryAggregate), false);
|
||||
assert.equal(isGameSessionOpenFault(unbranded), false);
|
||||
assert.equal(isGameSessionOpenFault(accessorSpoof), false);
|
||||
assert.equal(isGameSessionOpenFault(brandAccessorSpoof), false);
|
||||
assert.equal(accessorReads, 0);
|
||||
});
|
||||
|
||||
test('GameSessionHost disposes a module exactly once and becomes terminal after dispose', () => {
|
||||
const log: string[] = [];
|
||||
const sessions = new GameSessionHost(makeEntry(() => makeModule(log)));
|
||||
|
||||
Reference in New Issue
Block a user