From 3f4a80e782dc258182c35da195a0655917ba35f2 Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:04:00 +0000 Subject: [PATCH] Fix TypeError: crypto.randomUUID in ExampleWorkbench and SandboxBrowser --- .../examples/ExampleWorkbench.client.tsx | 11 +++++----- .../examples/SandboxBrowser.client.tsx | 5 +++-- src/utils/crypto.client.ts | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/utils/crypto.client.ts diff --git a/src/components/examples/ExampleWorkbench.client.tsx b/src/components/examples/ExampleWorkbench.client.tsx index 2d0054cf5..a20c3f9bd 100644 --- a/src/components/examples/ExampleWorkbench.client.tsx +++ b/src/components/examples/ExampleWorkbench.client.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { safeRandomUUID } from '~/utils/crypto.client' import { ArrowClockwiseIcon, BrowserIcon, @@ -419,7 +420,7 @@ export function ExampleWorkbench({ const environmentSnapshotRef = React.useRef< ExampleEnvironmentSnapshot | undefined >(undefined) - const browserChannelRef = React.useRef(crypto.randomUUID()) + const browserChannelRef = React.useRef(safeRandomUUID()) const compileRequestRef = React.useRef(0) const nextConsoleIdRef = React.useRef(0) const nextTerminalIdRef = React.useRef(1) @@ -785,7 +786,7 @@ export function ExampleWorkbench({ }) compileRequestRef.current += 1 cancelPreviewCapture('The preview changed before capture completed.') - browserChannelRef.current = crypto.randomUUID() + browserChannelRef.current = safeRandomUUID() webContainerSessionRef.current?.dispose() webContainerSessionRef.current = null setWebContainerSession(undefined) @@ -1032,7 +1033,7 @@ export function ExampleWorkbench({ handledRunDefinitionRef.current = definition if (signal?.aborted) { - const runId = crypto.randomUUID() + const runId = safeRandomUUID() return Promise.resolve({ ok: false, phase: 'aborted', @@ -1103,7 +1104,7 @@ export function ExampleWorkbench({ const request = compileRequestRef.current + 1 compileRequestRef.current = request - const runToken = crypto.randomUUID() + const runToken = safeRandomUUID() runTokenRef.current = runToken environmentSnapshotRef.current = createEmptyExampleEnvironmentSnapshot({ runId: runToken, @@ -2326,7 +2327,7 @@ export function ExampleWorkbench({ function capturePreview(tabId?: string) { cancelPreviewCapture('A newer screenshot replaced this capture.') - const requestId = crypto.randomUUID() + const requestId = safeRandomUUID() return new Promise((resolve, reject) => { const timeout = window.setTimeout(() => { diff --git a/src/components/examples/SandboxBrowser.client.tsx b/src/components/examples/SandboxBrowser.client.tsx index 836218583..b54ba6ced 100644 --- a/src/components/examples/SandboxBrowser.client.tsx +++ b/src/components/examples/SandboxBrowser.client.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { safeRandomUUID } from '~/utils/crypto.client' import { ArrowClockwiseIcon, ArrowLeftIcon, @@ -296,7 +297,7 @@ export function SandboxBrowser({ const note = annotationNote.trim() if (!note) return const annotation = { - id: crypto.randomUUID(), + id: safeRandomUUID(), note, target: annotationTarget, } satisfies SandboxBrowserAnnotation @@ -418,7 +419,7 @@ export function SandboxBrowser({ function submitCurrentAnnotation() { if (!annotationTarget) return const annotation = { - id: crypto.randomUUID(), + id: safeRandomUUID(), note: annotationNote.trim(), target: annotationTarget, } satisfies SandboxBrowserAnnotation diff --git a/src/utils/crypto.client.ts b/src/utils/crypto.client.ts new file mode 100644 index 000000000..a25e89713 --- /dev/null +++ b/src/utils/crypto.client.ts @@ -0,0 +1,22 @@ +/** + * A safe wrapper around crypto.randomUUID() that works in non-secure contexts + * (e.g. HTTP) and older browsers that do not implement randomUUID. + * + * Falls back to crypto.getRandomValues when available, then to a + * Date.now() + Math.random() string as a last resort. + */ +export function safeRandomUUID(): string { + const c = globalThis.crypto + + if (c?.randomUUID) { + return c.randomUUID() + } + + if (c?.getRandomValues) { + const values = new Uint32Array(4) + c.getRandomValues(values) + return Array.from(values, (v) => v.toString(16).padStart(8, '0')).join('-') + } + + return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}` +}