Skip to content

Commit 388c9d1

Browse files
author
Heiner Pöpping
committed
⚡ Explicitly initialize transfer nested functions to support tree-shaking
Moved the Comlink transfer handler registration from a module-level side effect to an explicit initialization function. This allows the package to be marked as side-effect free in package.json, enabling better bundle optimization. The initialization is now called specifically in the FrameWrapper and HostIframe components and includes checks to prevent redundant registrations.
1 parent 59e7bf9 commit 388c9d1

6 files changed

Lines changed: 49 additions & 39 deletions

File tree

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616
"default": "./dist/esm/index.js"
1717
}
1818
},
19-
"sideEffects": [
20-
"**/utils/transferNestedFunctions.*"
21-
],
19+
"sideEffects": false,
2220
"keywords": [
2321
"chayns",
2422
"chayns-toolkit",

src/host/iframe/HostIframe.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '../../types/IChaynsReact';
1414
import useUpdateData from './utils/useUpdateData';
1515
import { replaceStagingUrl } from "../../util/url";
16+
import { initTransferNestedFunctions } from '../../util/transferNestedFunctions';
1617

1718
type HostIframeProps = {
1819
iFrameProps: { [key: string]: unknown, name: string },
@@ -109,6 +110,8 @@ const HostIframe: FC<HostIframeProps> = ({
109110
// region expose data and functions to iframe
110111
useEffect(() => {
111112
if (ref.current?.contentWindow) {
113+
initTransferNestedFunctions();
114+
112115
const obj = {
113116
[iFrameProps.name]: {
114117
functions: {

src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import './util/transferNestedFunctions';
2-
31
export { default as ChaynsProvider, type ChaynsProviderProps } from './components/ChaynsProvider';
42
export { default as getDeviceInfo, getScreenSize, getClientDeviceInfo } from './util/deviceHelper';
53
export { default as ChaynsHost } from './host/ChaynsHost';

src/umd.index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import './util/transferNestedFunctions';
2-
31
export { default as getDeviceInfo, getScreenSize, getClientDeviceInfo } from './util/deviceHelper';
42
export * from './calls';
53
export * from './types/IChaynsReact';
Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,46 @@
11
// @ts-nocheck
22
import * as Comlink from 'comlink';
33

4-
Comlink.transferHandlers.set("FUNCTION", {
5-
canHandle: obj => {
6-
return obj && typeof obj === "object" && Object.values(obj).some(x => typeof x === 'function');
7-
},
8-
serialize(obj) {
9-
obj._functionKeys = [];
10-
const ports = [];
11-
Object.entries(obj).forEach(([k,v]) => {
12-
if(typeof v === 'function'){
13-
const { port1, port2 } = new MessageChannel();
14-
obj._functionKeys.push(k);
15-
Comlink.expose(obj[k], port1);
16-
obj[k] = port2;
17-
ports.push(port2);
18-
}
19-
})
20-
return [obj,ports];
21-
},
22-
deserialize(obj) {
23-
obj._functionKeys.forEach((x) => {
24-
// under certain conditions deserialize can be called more than once on same object
25-
if (obj[x] instanceof MessagePort) {
26-
obj[x].start();
27-
obj[x] = Comlink.wrap(obj[x]);
28-
}
29-
})
30-
return obj;
4+
const TRANSFER_HANDLER_NAME = 'FUNCTION';
5+
6+
let isInitialized = false;
7+
8+
export const initTransferNestedFunctions = () => {
9+
if (isInitialized || Comlink.transferHandlers.has(TRANSFER_HANDLER_NAME)) {
10+
isInitialized = true;
11+
return;
3112
}
32-
});
13+
14+
Comlink.transferHandlers.set(TRANSFER_HANDLER_NAME, {
15+
canHandle: obj => {
16+
return obj && typeof obj === 'object' && Object.values(obj).some(x => typeof x === 'function');
17+
},
18+
serialize(obj) {
19+
obj._functionKeys = [];
20+
const ports = [];
21+
Object.entries(obj).forEach(([k, v]) => {
22+
if (typeof v === 'function') {
23+
const { port1, port2 } = new MessageChannel();
24+
obj._functionKeys.push(k);
25+
Comlink.expose(obj[k], port1);
26+
obj[k] = port2;
27+
ports.push(port2);
28+
}
29+
});
30+
return [obj, ports];
31+
},
32+
deserialize(obj) {
33+
obj._functionKeys.forEach((x) => {
34+
// under certain conditions deserialize can be called more than once on same object
35+
if (obj[x] instanceof MessagePort) {
36+
obj[x].start();
37+
obj[x] = Comlink.wrap(obj[x]);
38+
}
39+
});
40+
return obj;
41+
}
42+
});
43+
44+
isInitialized = true;
45+
};
46+

src/wrapper/FrameWrapper.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
ToolbarChangeListenerResult,
2020
} from '../types/IChaynsReact';
2121
import { setTappHeight } from '../util/heightHelper';
22+
import { initTransferNestedFunctions } from '../util/transferNestedFunctions';
2223

2324
export class FrameWrapper implements IChaynsReact {
2425

@@ -261,10 +262,6 @@ export class FrameWrapper implements IChaynsReact {
261262
return this.exposedFunctions.scrollByY(value, duration);
262263
},
263264
createDialog: <I, R>(config: Dialog<I>) => {
264-
if (config.type === DialogType.INPUT && typeof config.formatter === 'function') {
265-
config.formatter = comlink.proxy(config.formatter);
266-
}
267-
268265
return new DialogHandler<R>(config, this.functions.openDialog, this.exposedFunctions.closeDialog, this.functions.dispatchEventToDialogClient, this.functions.addDialogClientEventListener);
269266
},
270267
closeDialog: async (dialogId) => {
@@ -340,6 +337,8 @@ export class FrameWrapper implements IChaynsReact {
340337
initialized = false;
341338

342339
constructor() {
340+
initTransferNestedFunctions();
341+
343342
const initialDataTag = document.querySelector('#__CHAYNS_DATA__');
344343
if (initialDataTag) {
345344
this.values = JSON.parse(initialDataTag.innerHTML) as ChaynsReactValues;

0 commit comments

Comments
 (0)