Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ignore messages from different source #403

Merged
merged 3 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/web/src/components/Messaging.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const buildMessageSummary = (params: BWEMessage): ComponentMessage | null => {
message,
isFromComponent,
name: 'render',
componentId: parseComponentId(message.componentId)!,
componentId: parseComponentId(message.containerId)!,
summary: `rendered <${type} ${formatProps(props, true).slice(
0,
64
Expand All @@ -106,7 +106,7 @@ const buildMessageSummary = (params: BWEMessage): ComponentMessage | null => {
message,
isFromComponent,
name: 'invoke',
componentId: parseComponentId(message.originator)!,
componentId: parseComponentId(message.containerId)!,
summary: `[${requestId.split('-')[0]}] called ${targetComponent}.${
method.split('::')[0]
}(${args})${isFromComponent ? '' : ' for'}`,
Expand Down
2 changes: 1 addition & 1 deletion packages/application/src/components/SandboxedIframe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ function buildSandboxedComponent({
},
context: {
Component,
componentId: '${id}',
componentPropsJson: ${componentPropsJson},
containerId: '${id}',
Fragment: __Preact.Fragment,
parentContainerId: '${parentContainerId}',
trust: ${JSON.stringify(trust)},
Expand Down
36 changes: 25 additions & 11 deletions packages/application/src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ export function onCallbackInvocation({
a component has invoked a callback passed to it as props by its parent component
post a component callback message to the parent iframe
*/
const { args, method, originator, requestId, targetId } = data;
const { args, containerId, method, requestId, targetId } = data;
sendMessage({
componentId: targetId!,
message: {
args,
method,
originator,
containerId,
requestId,
targetId,
type: 'component.callbackInvocation',
Expand Down Expand Up @@ -134,23 +134,37 @@ interface ChildComponent {
trust: ComponentTrust;
}

/**
* A component has been rendered, update it in the outer window
* TODO make a distinction between container-level renders and Component (e.g. trusted) renders
* currently containerId may refer to a Component, trusted or internally-defined, within a container
* @param containerId originating container
* @param childComponents set of child Components to be loaded dynamically
* @param debug debug configuration
* @param mountElement callback to mount the rendered element
* @param isComponentLoaded callback to determine whether a child Component is available or needs to be loaded
* @param loadComponent callback to fetch and compile child Component source
* @param getContainerRenderCount callback to get the number of times this Component has been rendered
* @param node serialized React node of the updated Component
* @param onMessageSent callback to be invoked when this Component's DOM posts a message to its container
*/
export function onRender({
data,
containerId,
childComponents,
debug,
mountElement,
isComponentLoaded,
loadComponent,
getContainerRenderCount,
node,
onMessageSent,
}: RenderHandlerParams) {
/* a component has been rendered and is ready to be updated in the outer window */
const { componentId, childComponents, node } = data;
const { children, ...props } = node?.props || { children: [] };

const componentChildren = createChildElements({
children,
depth: 0,
parentId: componentId,
parentId: containerId,
onMessageSent,
});
const element = createElement({
Expand All @@ -159,19 +173,19 @@ export function onRender({
? [
React.createElement('div', { className: 'dom-label' }, [
`[${
componentId.split('##')[0].split('/')[1]
} (${getContainerRenderCount(componentId)})]`,
containerId.split('##')[0].split('/')[1]
} (${getContainerRenderCount(containerId)})]`,
]),
]
: []),
...[componentChildren].flat(),
],
id: componentId,
id: containerId,
props,
type: node.type,
onMessageSent,
});
mountElement({ componentId, element });
mountElement({ componentId: containerId, element });

childComponents.forEach(
({
Expand All @@ -191,7 +205,7 @@ export function onRender({
componentId: childComponentId,
componentPath: source,
trust,
parentId: componentId,
parentId: containerId,
props: componentProps,
renderCount: 0,
});
Expand Down
41 changes: 28 additions & 13 deletions packages/application/src/hooks/useComponentTree.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MessagePayload } from '@bos-web-engine/common';
import type { ContainerPayload } from '@bos-web-engine/common';
import type { ComponentCompilerRequest } from '@bos-web-engine/compiler';
import { useSocial } from '@bos-web-engine/social-db';
import { useWallet } from '@bos-web-engine/wallet-selector-control';
Expand Down Expand Up @@ -100,17 +100,28 @@ export function useComponentTree({
);

const processMessage = useCallback(
(event: MessageEvent<MessagePayload>) => {
(event: MessageEvent<ContainerPayload>) => {
try {
if (typeof event.data !== 'object') {
if (
typeof event.data !== 'object' ||
!event.data?.type?.startsWith('component.')
) {
return;
}

const { data } = event;
if (data.type) {
// @ts-expect-error
const fromComponent = data.componentId || data.originator;
hooks?.messageReceived?.({ fromComponent, message: data });
hooks?.messageReceived?.({
fromComponent: data.containerId,
message: data,
});

const sourceIframe = document.getElementById(
`iframe-${data.containerId}`
) as HTMLIFrameElement;

if (sourceIframe?.contentWindow !== event.source) {
// this message came from a different iframe than the one specified in the message payload
return;
}

const onMessageSent = ({ toComponent, message }: BWEMessage) =>
Expand All @@ -122,7 +133,7 @@ export function useComponentTree({
if (data.targetId === null) {
return onApplicationMethodInvocation({
args: data.args,
componentId: data.originator,
componentId: data.containerId,
method: data.method,
onMessageSent,
requestId: data.requestId,
Expand All @@ -139,18 +150,22 @@ export function useComponentTree({
break;
}
case 'component.render': {
const { childComponents, containerId, node } = data;

onRender({
data,
childComponents,
containerId,
debug,
getContainerRenderCount: getComponentRenderCount,
isComponentLoaded: (c: string) => !!components[c],
loadComponent: (component) =>
loadComponent(component.componentId, component),
mountElement: ({ componentId, element }) => {
hooks?.componentRendered?.(componentId);
mountElement({ componentId, element, id: data.node.props?.id });
},
loadComponent: (component) =>
loadComponent(component.componentId, component),
isComponentLoaded: (c: string) => !!components[c],
node,
onMessageSent,
getContainerRenderCount: getComponentRenderCount,
});
break;
}
Expand Down
7 changes: 5 additions & 2 deletions packages/application/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import type {
BOSModule,
ComponentCallbackInvocation,
ComponentCallbackResponse,
ComponentRender,
ComponentChildMetadata,
ComponentTrust,
MessagePayload,
SerializedArgs,
SerializedNode,
} from '@bos-web-engine/common';
import type {
ComponentCompilerRequest,
Expand Down Expand Up @@ -50,7 +51,8 @@ export interface ComponentMetrics {
}

export interface RenderHandlerParams {
data: ComponentRender;
childComponents: ComponentChildMetadata[];
containerId: string;
debug?: WebEngineDebug;
mountElement: ({
componentId,
Expand All @@ -62,6 +64,7 @@ export interface RenderHandlerParams {
isComponentLoaded(componentId: string): boolean;
loadComponent(component: ComponentInstance): void;
getContainerRenderCount(containerId: string): number;
node: SerializedNode;
onMessageSent: OnMessageSentCallback;
}

Expand Down
16 changes: 10 additions & 6 deletions packages/common/src/types/messaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface PostMessageParams {
export interface ComponentCallbackInvocation extends PostMessageParams {
args: SerializedArgs;
method: string;
originator: string;
containerId: string;
requestId: string;
targetId: string | null;
type: ComponentCallbackInvocationType;
Expand All @@ -43,7 +43,7 @@ export interface ComponentCallbackResponse extends PostMessageParams {

export interface ComponentRender extends PostMessageParams {
childComponents: ComponentChildMetadata[];
componentId: string;
containerId: string;
node: SerializedNode;
trust: ComponentTrust;
type: ComponentRenderType;
Expand All @@ -62,9 +62,13 @@ export interface DomCallback {
type: ComponentDomCallbackType;
}

export type MessagePayload =
// payloads sent by the application to a container
export type ApplicationPayload = ComponentUpdate | DomCallback;

// payloads sent by a container to the application
export type ContainerPayload =
| ComponentCallbackInvocation
| ComponentCallbackResponse
| DomCallback
| ComponentRender
| ComponentUpdate;
| ComponentRender;

export type MessagePayload = ApplicationPayload | ContainerPayload;
14 changes: 7 additions & 7 deletions packages/container/src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export function initContainer({
},
context: {
Component,
componentId,
componentPropsJson,
containerId,
Fragment,
parentContainerId,
trust,
Expand Down Expand Up @@ -51,7 +51,7 @@ export function initContainer({
});

const { commit } = composeRenderMethods({
componentId,
containerId,
isComponent: (c) => c === Component,
isExternalComponent: (c) => !('isRootContainerComponent' in c),
isFragment: (c) => c === Fragment,
Expand All @@ -74,7 +74,7 @@ export function initContainer({

const processEvent = buildEventHandler({
callbacks,
containerId: componentId,
containerId,
deserializeArgs,
deserializeProps,
initExternalCallbackInvocation,
Expand All @@ -96,22 +96,22 @@ export function initContainer({
if (!updatedProps.bwe) {
updatedProps.bwe = {};
}
updatedProps.bwe.componentId = componentId;
updatedProps.bwe.componentId = containerId;

return updatedProps;
}),
});

const deserializedProps = deserializeProps({
containerId: componentId,
containerId,
props: componentPropsJson,
});

const props = {
...deserializedProps,
bwe: {
...deserializedProps,
componentId,
componentId: containerId,
},
};

Expand All @@ -120,7 +120,7 @@ export function initContainer({
return invokeApplicationCallback({
args,
callbacks,
containerId: componentId,
containerId,
initExternalCallbackInvocation,
invokeInternalCallback,
method,
Expand Down
4 changes: 2 additions & 2 deletions packages/container/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function buildEventHandler({

switch (event.data.type) {
case 'component.callbackInvocation': {
let { args, method, originator, requestId } = event.data;
let { args, containerId, method, requestId } = event.data;
try {
result = invokeCallbackFromEvent({ args, method });
} catch (e: any) {
Expand All @@ -113,7 +113,7 @@ export function buildEventHandler({
containerId,
requestId,
result: value,
targetId: originator,
targetId: containerId,
});
}
};
Expand Down
6 changes: 3 additions & 3 deletions packages/container/src/messaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function composeMessagingMethods() {
postMessage<ComponentCallbackInvocation>({
args: serializeArgs({ args, callbacks, containerId }),
method,
originator: containerId,
containerId,
requestId,
targetId,
type: 'component.callbackInvocation',
Expand Down Expand Up @@ -75,13 +75,13 @@ export function composeMessagingMethods() {

function postComponentRenderMessage({
childComponents,
componentId,
containerId,
node,
trust,
}: PostMessageComponentRenderParams): void {
postMessage<ComponentRender>({
childComponents,
componentId,
containerId,
node,
trust,
type: 'component.render',
Expand Down
Loading
Loading