From 0f1354c490eb5b81af0c567cb04596bc774ba00e Mon Sep 17 00:00:00 2001 From: Andy Haynes Date: Fri, 8 Dec 2023 16:58:57 -0800 Subject: [PATCH 1/3] refactor: pass callbacks instead of Components --- packages/container/src/container.ts | 6 +++--- packages/container/src/render.ts | 16 ++++++++-------- packages/container/src/types.ts | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/container/src/container.ts b/packages/container/src/container.ts index 6cef9186..1ca7eb8f 100644 --- a/packages/container/src/container.ts +++ b/packages/container/src/container.ts @@ -41,10 +41,10 @@ export function initContainer({ }); const { commit } = composeRenderMethods({ - BWEComponent, - Component, componentId, - Fragment, + isComponent: (c) => c === Component, + isFragment: (c) => c === Fragment, + isRootComponent: (c) => c === BWEComponent, postComponentRenderMessage, serializeNode, trust, diff --git a/packages/container/src/render.ts b/packages/container/src/render.ts index 32a97d67..4a31fc83 100644 --- a/packages/container/src/render.ts +++ b/packages/container/src/render.ts @@ -1,4 +1,4 @@ -import type { ComponentChildren, VNode } from 'preact'; +import type { ComponentChildren, ComponentType, VNode } from 'preact'; import type { BuildSafeProxyCallback, @@ -50,10 +50,10 @@ interface RenderedVNode extends VNode { type DispatchRenderCallback = (vnode: VNode) => void; export const composeRenderMethods: ComposeRenderMethodsCallback = ({ - BWEComponent, - Component, componentId, - Fragment, + isRootComponent, + isComponent, + isFragment, postComponentRenderMessage, serializeNode, trust, @@ -121,11 +121,11 @@ export const composeRenderMethods: ComposeRenderMethodsCallback = ({ return node; } - if (node.type === Fragment) { + if (isFragment(node.type as ComponentType)) { const fragmentChildren = renderedChildren || []; if ( fragmentChildren.length === 1 && - fragmentChildren[0]?.type === BWEComponent + isRootComponent(fragmentChildren[0]?.type as ComponentType) ) { // this node is the root of a component defined in the container return parseRenderedTree( @@ -150,8 +150,8 @@ export const composeRenderMethods: ComposeRenderMethodsCallback = ({ ) : node.props; - if (typeof node.type === 'function' && node.type !== Component) { - if (isBWEComponent(node) && node.type !== BWEComponent) { + if (typeof node.type === 'function' && isComponent(node.type)) { + if (isBWEComponent(node) && !isRootComponent(node.type)) { const componentNode = buildBWEComponentNode( node as BWEComponentNode, renderedChildren diff --git a/packages/container/src/types.ts b/packages/container/src/types.ts index 53abac41..f7c20046 100644 --- a/packages/container/src/types.ts +++ b/packages/container/src/types.ts @@ -155,10 +155,10 @@ export interface ComponentUpdate extends PostMessageParams { } interface ComposeRenderMethodsParams { - BWEComponent: FunctionComponent; - Component: Function; componentId: string; - Fragment: FunctionComponent; + isComponent: (component: Function) => boolean; + isFragment: (component: Function) => boolean; + isRootComponent: (component: Function) => boolean; postComponentRenderMessage: PostMessageComponentRenderCallback; serializeNode: SerializeNodeCallback; trust: ComponentTrust; From 21a0430b1e5b1e7f50823d6c7f48ad6eb8651f9d Mon Sep 17 00:00:00 2001 From: Andy Haynes Date: Fri, 8 Dec 2023 17:16:45 -0800 Subject: [PATCH 2/3] feat: support Component alongside Widget --- packages/compiler/src/parser.ts | 4 ++-- packages/container/src/container.ts | 4 ++++ packages/container/src/render.ts | 7 ++++++- packages/container/src/serialize.ts | 10 ++++++---- packages/container/src/types.ts | 4 ++++ packages/iframe/src/SandboxedIframe.tsx | 6 ++++-- 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/compiler/src/parser.ts b/packages/compiler/src/parser.ts index 5274e7ea..28e130c7 100644 --- a/packages/compiler/src/parser.ts +++ b/packages/compiler/src/parser.ts @@ -1,7 +1,7 @@ function parseWidgetRenders(transpiledComponent: string) { const functionOffset = 'createElement'.length; const componentRegex = - /createElement\(Widget,\s*\{(?:[\w\W]*?)(?:\s*src:\s*["|'](?((([a-z\d]+[\-_])*[a-z\d]+\.)*([a-z\d]+[\-_])*[a-z\d]+)\/[\w.-]+))["|']/gi; + /createElement\((?:Widget|Component),\s*\{(?:[\w\W]*?)(?:\s*src:\s*["|'](?((([a-z\d]+[\-_])*[a-z\d]+\.)*([a-z\d]+[\-_])*[a-z\d]+)\/[\w.-]+))["|']/gi; return [...transpiledComponent.matchAll(componentRegex)].map((match) => { const openParenIndex = match.index! + functionOffset; let parenCount = 1; @@ -53,7 +53,7 @@ export function parseChildComponents( const signaturePrefix = `${componentName},{__bweMeta:{parentMeta:props.__bweMeta},`; return componentSource.replaceAll( expression, - expression.replace(/Widget,\s*\{/, signaturePrefix) + expression.replace(/(Widget|Component),\s*\{/, signaturePrefix) ); }, }; diff --git a/packages/container/src/container.ts b/packages/container/src/container.ts index 1ca7eb8f..451c4b70 100644 --- a/packages/container/src/container.ts +++ b/packages/container/src/container.ts @@ -20,6 +20,7 @@ export function initContainer({ parentContainerId, trust, updateContainerProps, + Widget, // TODO remove when no longer supported }, }: InitContainerParams) { const callbacks: { [key: string]: Function } = {}; @@ -35,6 +36,8 @@ export function initContainer({ composeSerializationMethods({ buildRequest, callbacks, + isComponent: (c) => c === Component, + isWidget: (c) => c === Widget, // TODO remove when no longer supported parentContainerId, postCallbackInvocationMessage, requests, @@ -45,6 +48,7 @@ export function initContainer({ isComponent: (c) => c === Component, isFragment: (c) => c === Fragment, isRootComponent: (c) => c === BWEComponent, + isWidget: (c) => c === Widget, // TODO remove when no longer supported postComponentRenderMessage, serializeNode, trust, diff --git a/packages/container/src/render.ts b/packages/container/src/render.ts index 4a31fc83..4a09593f 100644 --- a/packages/container/src/render.ts +++ b/packages/container/src/render.ts @@ -54,6 +54,7 @@ export const composeRenderMethods: ComposeRenderMethodsCallback = ({ isRootComponent, isComponent, isFragment, + isWidget, // TODO remove when no longer supported postComponentRenderMessage, serializeNode, trust, @@ -150,7 +151,11 @@ export const composeRenderMethods: ComposeRenderMethodsCallback = ({ ) : node.props; - if (typeof node.type === 'function' && isComponent(node.type)) { + if ( + typeof node.type === 'function' && + !isComponent(node.type) && + !isWidget(node.type) + ) { if (isBWEComponent(node) && !isRootComponent(node.type)) { const componentNode = buildBWEComponentNode( node as BWEComponentNode, diff --git a/packages/container/src/serialize.ts b/packages/container/src/serialize.ts index 81447b12..eeea9585 100644 --- a/packages/container/src/serialize.ts +++ b/packages/container/src/serialize.ts @@ -31,6 +31,8 @@ export const composeSerializationMethods: ComposeSerializationMethodsCallback = ({ buildRequest, callbacks, + isComponent, + isWidget, parentContainerId, postCallbackInvocationMessage, requests, @@ -201,16 +203,16 @@ export const composeSerializationMethods: ComposeSerializationMethodsCallback = componentPath, parentComponentId, }: BuildComponentIdParams) { - // TODO warn on missing instanceId ('s id prop) here? + // TODO warn on missing instanceId ('s id prop) here? return [componentPath, instanceId?.toString(), parentComponentId].join( '##' ); } /** - * Serialize a sandboxed component + * Serialize a sandboxed component * @param parentId ID of the parent Component - * @param props Props passed to the component + * @param props Props passed to the component */ const serializeChildComponent = ({ parentId, @@ -294,7 +296,7 @@ export const composeSerializationMethods: ComposeSerializationMethodsCallback = }); if (typeof type === 'function') { - if (type.name !== 'Widget') { + if (!isWidget(type) && !isComponent(type)) { throw new Error(`unrecognized Component function ${type.name}`); } diff --git a/packages/container/src/types.ts b/packages/container/src/types.ts index f7c20046..3966e671 100644 --- a/packages/container/src/types.ts +++ b/packages/container/src/types.ts @@ -159,6 +159,7 @@ interface ComposeRenderMethodsParams { isComponent: (component: Function) => boolean; isFragment: (component: Function) => boolean; isRootComponent: (component: Function) => boolean; + isWidget: (component: Function) => boolean; // TODO remove when no longer supported postComponentRenderMessage: PostMessageComponentRenderCallback; serializeNode: SerializeNodeCallback; trust: ComponentTrust; @@ -173,6 +174,8 @@ export type ComposeRenderMethodsCallback = ( export interface ComposeSerializationMethodsParams { buildRequest: BuildRequestCallback; callbacks: CallbackMap; + isComponent: (component: Function) => boolean; + isWidget: (component: Function) => boolean; // TODO remove when no longer supported parentContainerId: string | null; postCallbackInvocationMessage: PostMessageComponentInvocationCallback; requests: RequestMap; @@ -236,6 +239,7 @@ export interface InitContainerParams { props: any; trust: ComponentTrust; updateContainerProps: UpdateContainerPropsCallback; + Widget: Function; // TODO remove when no longer supported }; } diff --git a/packages/iframe/src/SandboxedIframe.tsx b/packages/iframe/src/SandboxedIframe.tsx index 14d90653..6bb4df59 100644 --- a/packages/iframe/src/SandboxedIframe.tsx +++ b/packages/iframe/src/SandboxedIframe.tsx @@ -43,7 +43,8 @@ function buildSandboxedComponent({ const initContainer = ${initContainer.toString()}; - // placeholder to prevent references from breaking + // placeholder function to bind to Component/Widget references + function Component() {} function Widget() {} function useComponentCallback(cb, args) { @@ -79,7 +80,7 @@ function buildSandboxedComponent({ }, context: { BWEComponent, - Component: Widget, + Component, componentId: '${id}', componentPropsJson: ${componentPropsJson}, Fragment: Preact.Fragment, @@ -93,6 +94,7 @@ function buildSandboxedComponent({ Preact.render(createElement(BWEComponent), document.body); } }, + Widget, }, }); From c32f9da19645e1ac9e02655f8dcae470278ebed7 Mon Sep 17 00:00:00 2001 From: Andy Haynes Date: Fri, 8 Dec 2023 17:30:55 -0800 Subject: [PATCH 3/3] feat: warning message --- packages/container/src/serialize.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/container/src/serialize.ts b/packages/container/src/serialize.ts index eeea9585..64635571 100644 --- a/packages/container/src/serialize.ts +++ b/packages/container/src/serialize.ts @@ -300,6 +300,12 @@ export const composeSerializationMethods: ComposeSerializationMethodsCallback = throw new Error(`unrecognized Component function ${type.name}`); } + if (isWidget(type)) { + console.warn( + ' will be deprecated in upcoming versions of BOS Web Engine. Please update your code to reference instead.' + ); + } + const { child, placeholder } = serializeChildComponent({ parentId, props,