fix(companion): type-guard event wait name validation
This commit is contained in:
@@ -820,6 +820,18 @@
|
|||||||
],
|
],
|
||||||
"test_status": "pnpm test:run src/companion/runtimeClient.test.ts src/companion/platformClients.test.ts src/companion/heartbeatLoop.test.ts src/companion/platformClients.integration.test.ts + pnpm typecheck passing"
|
"test_status": "pnpm test:run src/companion/runtimeClient.test.ts src/companion/platformClients.test.ts src/companion/heartbeatLoop.test.ts src/companion/platformClients.integration.test.ts + pnpm typecheck passing"
|
||||||
},
|
},
|
||||||
|
"companion-runtime-event-name-type-guard": {
|
||||||
|
"status": "completed",
|
||||||
|
"date": "2026-02-17",
|
||||||
|
"updated": "2026-02-17",
|
||||||
|
"summary": "Hardened runtime event-name validation with explicit string type guards so `waitForEvent()`/`waitForAnyEvent()` reject non-string inputs deterministically.",
|
||||||
|
"files_modified": [
|
||||||
|
"src/companion/runtimeClient.ts",
|
||||||
|
"src/companion/runtimeClient.test.ts",
|
||||||
|
"docs/plans/state.json"
|
||||||
|
],
|
||||||
|
"test_status": "pnpm test:run src/companion/runtimeClient.test.ts src/companion/platformClients.test.ts src/companion/heartbeatLoop.test.ts src/companion/platformClients.integration.test.ts + pnpm typecheck passing"
|
||||||
|
},
|
||||||
"browser-tools-activation-clarity": {
|
"browser-tools-activation-clarity": {
|
||||||
"status": "completed",
|
"status": "completed",
|
||||||
"date": "2026-02-17",
|
"date": "2026-02-17",
|
||||||
|
|||||||
@@ -350,6 +350,9 @@ describe('CompanionRuntimeClient', () => {
|
|||||||
|
|
||||||
expect(() => client.waitForEvent('')).toThrow('eventName must be a non-empty string');
|
expect(() => client.waitForEvent('')).toThrow('eventName must be a non-empty string');
|
||||||
expect(() => client.waitForEvent(' ')).toThrow('eventName must be a non-empty string');
|
expect(() => client.waitForEvent(' ')).toThrow('eventName must be a non-empty string');
|
||||||
|
expect(() => client.waitForEvent(123 as unknown as string)).toThrow(
|
||||||
|
'eventName must be a non-empty string',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('waitForEvent supports AbortSignal cancellation', async () => {
|
it('waitForEvent supports AbortSignal cancellation', async () => {
|
||||||
@@ -585,6 +588,9 @@ describe('CompanionRuntimeClient', () => {
|
|||||||
expect(() => client.waitForAnyEvent(['agent.stream', ' '])).toThrow(
|
expect(() => client.waitForAnyEvent(['agent.stream', ' '])).toThrow(
|
||||||
'eventNames must not contain empty values',
|
'eventNames must not contain empty values',
|
||||||
);
|
);
|
||||||
|
expect(() => client.waitForAnyEvent(['agent.stream', 123 as unknown as string])).toThrow(
|
||||||
|
'eventNames must not contain empty values',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('connects and performs node registration + capability discovery', async () => {
|
it('connects and performs node registration + capability discovery', async () => {
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ export class CompanionRuntimeClient {
|
|||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
},
|
},
|
||||||
): Promise<TData> {
|
): Promise<TData> {
|
||||||
if (eventName.trim().length === 0) {
|
if (typeof eventName !== 'string' || eventName.trim().length === 0) {
|
||||||
throw new Error('eventName must be a non-empty string');
|
throw new Error('eventName must be a non-empty string');
|
||||||
}
|
}
|
||||||
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
|
||||||
@@ -505,7 +505,11 @@ export class CompanionRuntimeClient {
|
|||||||
if (eventNames.length === 0) {
|
if (eventNames.length === 0) {
|
||||||
throw new Error('eventNames must contain at least one event name');
|
throw new Error('eventNames must contain at least one event name');
|
||||||
}
|
}
|
||||||
if (eventNames.some((eventName) => eventName.trim().length === 0)) {
|
if (
|
||||||
|
eventNames.some(
|
||||||
|
(eventName) => typeof eventName !== 'string' || eventName.trim().length === 0,
|
||||||
|
)
|
||||||
|
) {
|
||||||
throw new Error('eventNames must not contain empty values');
|
throw new Error('eventNames must not contain empty values');
|
||||||
}
|
}
|
||||||
const eventNameSet = new Set(eventNames);
|
const eventNameSet = new Set(eventNames);
|
||||||
|
|||||||
Reference in New Issue
Block a user