Skip to content

Commit

Permalink
fix: nativeEmitter safe emit (gronxb#42)
Browse files Browse the repository at this point in the history
* fix: warning nativeEmitter null check

* fix: null check

* fix: safe emit

* chore: lint off

* fix: change emitter

* fix: clear batched event
  • Loading branch information
gronxb authored May 12, 2024
1 parent d03ecd8 commit 5b9dc22
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 26 deletions.
25 changes: 11 additions & 14 deletions packages/react-native/src/createWebView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
INJECT_BRIDGE_STATE,
INJECT_DEBUG,
LogType,
SAFE_NATIVE_EMITTER_EMIT,
} from "./integrations";
import { handleRegisterWebMethod } from "./integrations/handleRegisterWebMethod";
import type { BridgeWebView } from "./types/webview";
Expand Down Expand Up @@ -48,11 +49,9 @@ export const createWebView = <BridgeObject extends Bridge>({
const emitter = createEvents();

bridge.subscribe((state) => {
_webviewRef.current?.injectJavaScript(`
window.nativeEmitter.emit('bridgeStateChange', ${JSON.stringify(
state,
)});
`);
_webviewRef.current?.injectJavaScript(
SAFE_NATIVE_EMITTER_EMIT("bridgeStateChange", state),
);
});

return {
Expand All @@ -72,9 +71,9 @@ export const createWebView = <BridgeObject extends Bridge>({
const initialState = useMemo(
() =>
Object.fromEntries(
Object.entries(bridge.getState() ?? {})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.filter(([_, value]) => typeof value !== "function"),
Object.entries(bridge.getState() ?? {}).filter(
([_, value]) => typeof value !== "function",
),
) as Record<string, Primitive>,
[],
);
Expand Down Expand Up @@ -123,11 +122,9 @@ export const createWebView = <BridgeObject extends Bridge>({
return;
}
case "getBridgeState": {
_webviewRef.current?.injectJavaScript(`
window.nativeEmitter.emit('bridgeStateChange', ${JSON.stringify(
bridge.getState(),
)});
`);
_webviewRef.current?.injectJavaScript(
SAFE_NATIVE_EMITTER_EMIT("bridgeStateChange", bridge.getState()),
);
return;
}
case "registerWebMethod": {
Expand Down Expand Up @@ -190,7 +187,7 @@ export const createWebView = <BridgeObject extends Bridge>({
.filter(Boolean)
.join("\n")}
injectedJavaScript={[
console && INJECT_DEBUG,
debug && INJECT_DEBUG,
props.injectedJavaScript,
"true;",
]
Expand Down
39 changes: 27 additions & 12 deletions packages/react-native/src/integrations/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,7 @@ export const handleBridge = async ({

const _method = _bridge[method];
const handleThrow = () => {
webview.injectJavaScript(`
window.nativeEmitter.emit('${method}-${eventId}', {}, true);
true;
`);
webview.injectJavaScript(SAFE_NATIVE_EMITTER_THROW(`${method}-${eventId}`));
};
if (!(method in _bridge)) {
handleThrow();
Expand All @@ -99,13 +95,9 @@ export const handleBridge = async ({
try {
const response = await _method?.(...(args ?? []));

webview.injectJavaScript(`
window.nativeEmitter.emit('${method}-${eventId}',${JSON.stringify(
response,
)});
true;
`);
webview.injectJavaScript(
SAFE_NATIVE_EMITTER_EMIT(`${method}-${eventId}`, response),
);
} catch (error) {
handleThrow();
console.error(error);
Expand All @@ -121,3 +113,26 @@ export const INJECT_BRIDGE_STATE = (
) => `
window.__bridgeInitialState__ = ${JSON.stringify(initialState)};
`;

export const SAFE_NATIVE_EMITTER_EMIT = (eventName: string, data: unknown) => {
const dataString = JSON.stringify(data);
return `
if (window.nativeEmitter) {
window.nativeEmitter.emit('${eventName}', ${dataString});
} else {
window.nativeBatchedEvents = window.nativeBatchedEvents || [];
window.nativeBatchedEvents.push(['${eventName}', ${dataString}]);
}
true;
`;
};

export const SAFE_NATIVE_EMITTER_THROW = (eventName: string) => `
if (window.nativeEmitter) {
window.nativeEmitter.emit('${eventName}', {}, true);
} else {
window.nativeBatchedEvents = window.nativeBatchedEvents || [];
window.nativeBatchedEvents.push(['${eventName}', {}, true]);
}
true;
`;
1 change: 1 addition & 0 deletions packages/web/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare global {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
__bridgeInitialState__?: Record<string, any>;
nativeEmitter?: EventEmitter<DefaultEvents>;
nativeBatchedEvents?: [string, ...any][];
webEmitter?: EventEmitter<DefaultEvents>;
ReactNativeWebView: {
postMessage: (data: string) => void;
Expand Down
5 changes: 5 additions & 0 deletions packages/web/src/linkBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ export const linkBridge = <
},
});

for (const [eventName, ...args] of window.nativeBatchedEvents ?? []) {
emitter.emit(eventName, ...args);
}
window.nativeBatchedEvents = [];

onReady?.(proxy);
return proxy;
};

0 comments on commit 5b9dc22

Please sign in to comment.