Skip to content

Commit a0d72c7

Browse files
committed
Fix: app crashed on open with no error — unguarded Intl call at render time
Intl.DateTimeFormat().resolvedOptions().timeZone ran as a bare destructuring default with no try/catch, unlike every other side-effecting call in this file (theme fetch, AsyncStorage, polling). Some release-mode Hermes builds ship without full Intl support, so accessing it there throws — and since this runs at render time before any error boundary exists, it's an uncaught fatal with no red-box/dev-menu output, which matches "crashes on open, no error, sudden exit" exactly (only reproduces in release builds, not debug, since debug has Metro's overlay to at least surface something). Wrapped it in a helper that falls back to "UTC" on any failure — same fallback behavior AsyncStorage/theme-fetch already use elsewhere in this file.
1 parent 0a58937 commit a0d72c7

2 files changed

Lines changed: 32 additions & 10 deletions

File tree

‎dist/useChattyChat.js‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,28 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
33
import { ChattyClient, } from "./api";
44
import { getOrCreateSessionId, newSession } from "./session";
55
const MSGS_KEY = (botId, host) => `chatty_msgs_${botId}_${host}`;
6+
// Real IANA zone (e.g. "Asia/Colombo"), not a literal "UTC" default — the assistant uses
7+
// this to skip asking the visitor for their timezone (see widget_brain.py's scheduling
8+
// prompt), same as the web widget already does via the same Intl call. Guarded because
9+
// some release-mode Hermes builds ship without full Intl.DateTimeFormat support — this ran
10+
// unguarded as a destructuring default (i.e. at render time, outside any try/catch) and a
11+
// throw there is an uncaught render-time exception with no JS error boundary to catch it,
12+
// which crashes the whole app on open with no visible error.
13+
function _detectTimezone() {
14+
try {
15+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
16+
}
17+
catch {
18+
return "UTC";
19+
}
20+
}
621
/**
722
* Drives a full Chatty conversation: loads bot theme/config, manages the
823
* persistent session id, sends messages, and polls for human-agent replies.
924
* This is the native-SDK equivalent of widget.js's embed iframe lifecycle.
1025
*/
1126
export function useChattyChat(options) {
12-
// Real IANA zone (e.g. "Asia/Colombo"), not a literal "UTC" default — the assistant uses
13-
// this to skip asking the visitor for their timezone (see widget_brain.py's scheduling
14-
// prompt), same as the web widget already does via the same Intl call. Available in both
15-
// Hermes and JSC on RN 0.72+ (this SDK's minimum).
16-
const { botId, baseUrl, host, hostKey = "app", pollIntervalMs = 4000, visitorTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone, } = options;
27+
const { botId, baseUrl, host, hostKey = "app", pollIntervalMs = 4000, visitorTimezone = _detectTimezone(), } = options;
1728
const currentClient = useMemo(() => new ChattyClient({ botId, baseUrl, host }), [botId, baseUrl, host]);
1829
const clientRef = useRef(currentClient);
1930
clientRef.current = currentClient;

‎src/useChattyChat.ts‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,30 @@ export interface UseChattyChatResult {
4242
clearChat: () => Promise<void>;
4343
}
4444

45+
// Real IANA zone (e.g. "Asia/Colombo"), not a literal "UTC" default — the assistant uses
46+
// this to skip asking the visitor for their timezone (see widget_brain.py's scheduling
47+
// prompt), same as the web widget already does via the same Intl call. Guarded because
48+
// some release-mode Hermes builds ship without full Intl.DateTimeFormat support — this ran
49+
// unguarded as a destructuring default (i.e. at render time, outside any try/catch) and a
50+
// throw there is an uncaught render-time exception with no JS error boundary to catch it,
51+
// which crashes the whole app on open with no visible error.
52+
function _detectTimezone(): string {
53+
try {
54+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
55+
} catch {
56+
return "UTC";
57+
}
58+
}
59+
4560
/**
4661
* Drives a full Chatty conversation: loads bot theme/config, manages the
4762
* persistent session id, sends messages, and polls for human-agent replies.
4863
* This is the native-SDK equivalent of widget.js's embed iframe lifecycle.
4964
*/
5065
export function useChattyChat(options: UseChattyChatOptions): UseChattyChatResult {
51-
// Real IANA zone (e.g. "Asia/Colombo"), not a literal "UTC" default — the assistant uses
52-
// this to skip asking the visitor for their timezone (see widget_brain.py's scheduling
53-
// prompt), same as the web widget already does via the same Intl call. Available in both
54-
// Hermes and JSC on RN 0.72+ (this SDK's minimum).
5566
const {
5667
botId, baseUrl, host, hostKey = "app", pollIntervalMs = 4000,
57-
visitorTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone,
68+
visitorTimezone = _detectTimezone(),
5869
} = options;
5970

6071
const currentClient = useMemo(() => new ChattyClient({ botId, baseUrl, host }), [botId, baseUrl, host]);

0 commit comments

Comments
 (0)