Files
lens/src/test-utils/channel-fakes/override-messaging-from-main-to-window.ts
T
Sebastian Malton 5a5eda935b Add better type safety around Channels (#6133)
* Add better type safety around Channels

- Reallow non-JSON serializable complex types

- Remove unnecessary JSON serialization step to IPC

- Remove unnecesary injectable-ization of MessageChannel and
  RequestChannel declarations

- Add channel listener injectable getter function to remove general need
  for type casting and improve type safety

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add check to verify data in IPC related tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix implementation in light of new safety check in tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix listener ID clash potential

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Switch to not forcing split of request channel handlers being seperate from the listener decl

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move message channels to changed signature too

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix not registering listener

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test imports

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Refactor listening of different channel kinds

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add test covering new checking code for request channel handlers

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Signed-off-by: Sebastian Malton <sebastian@malton.name>
2022-10-13 07:50:19 -04:00

80 lines
2.9 KiB
TypeScript

/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token";
import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import { getOrInsert, getOrInsertSet } from "../../common/utils";
import type { SendToViewArgs } from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
import { deserialize, serialize } from "v8";
type ListenerSet = Set<MessageChannelListener<any>>;
type WindowListenerMap = Map<string, ListenerSet>;
type ListenerFakeMap = Map<string, WindowListenerMap>;
export interface OverriddenWindowMessaging {
sendToWindow(windowId: string, args: SendToViewArgs): void;
overrideEnlistForWindow(windowDi: DiContainer, windowId: string): void;
}
export const overrideMessagingFromMainToWindow = (): OverriddenWindowMessaging => {
const messageChannelListenerFakesForRenderer: ListenerFakeMap = new Map();
const getWindowListeners = (channelId: string, windowId: string) => {
const channelListeners = getOrInsert<string, WindowListenerMap>(
messageChannelListenerFakesForRenderer,
channelId,
new Map(),
);
return getOrInsertSet(channelListeners, windowId);
};
return {
overrideEnlistForWindow: (windowDi, windowId) => {
windowDi.override(
enlistMessageChannelListenerInjectableInRenderer,
() => (listener) => {
const windowListeners = getWindowListeners(
listener.channel.id,
windowId,
);
windowListeners.add(listener);
return () => {
windowListeners.delete(listener);
};
},
);
},
sendToWindow: (windowId, { channel, data, frameInfo }) => {
try {
data = deserialize(serialize(data));
} catch (error) {
throw new Error(`Tried to send a message to channel "${channel}" that is not compatible with StructuredClone: ${error}`);
}
const windowListeners = getWindowListeners(channel, windowId);
if (frameInfo) {
throw new Error(
`Tried to send message to frame "${frameInfo.frameId}" in process "${frameInfo.processId}" using channel "${channel}" which isn't supported yet.`,
);
}
if (windowListeners.size === 0) {
throw new Error(
`Tried to send message to channel "${channel}" but there where no listeners. Current channels with listeners: "${[
...messageChannelListenerFakesForRenderer.keys(),
].join('", "')}"`,
);
}
windowListeners.forEach((listener) => listener.handler(data));
},
};
};