From b1631f7b697bf125ebb2985f1d6db9b8003f3f63 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 8 Oct 2026 15:07:19 +0000 Subject: [PATCH] docs(installWebGPU): bare navigator works on react-native-worklets 0.13+ The Worklets babel plugin treats navigator as a known global since react-native-worklets 0.13.0, so the globalThis.navigator workaround is only needed on older versions. --- apps/docs/content/api/install-webgpu.mdx | 10 +++++++--- packages/webgpu/src/install.ts | 13 ++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/docs/content/api/install-webgpu.mdx b/apps/docs/content/api/install-webgpu.mdx index aace18728..c2a55e22b 100644 --- a/apps/docs/content/api/install-webgpu.mdx +++ b/apps/docs/content/api/install-webgpu.mdx @@ -76,7 +76,7 @@ runOnRuntime(runtime, gpuWork)(device); ### navigator.gpu on a worklet runtime -After `installWebGPU()`, read `navigator` through `globalThis.navigator` inside a worklet. The Worklets babel plugin does not currently treat a bare `navigator` as a known global, so without the prefix it captures the main runtime's `navigator` object by closure instead of reading the one installed on the worklet runtime. This is fixed upstream ([software-mansion/react-native-reanimated#10364](https://github.com/software-mansion/react-native-reanimated/pull/10364)); once you are on a version of `react-native-worklets` that includes it, a bare `navigator` works and the prefix is no longer needed. +After `installWebGPU()`, `navigator.gpu` is available inside the worklet: ```tsx twoslash import { installWebGPU } from "react-native-webgpu"; @@ -85,13 +85,17 @@ import { runOnUI } from "react-native-worklets"; runOnUI(() => { "worklet"; installWebGPU(); - const format = globalThis.navigator.gpu.getPreferredCanvasFormat(); - globalThis.navigator.gpu.requestAdapter().then((adapter) => { + const format = navigator.gpu.getPreferredCanvasFormat(); + navigator.gpu.requestAdapter().then((adapter) => { // … }); })(); ``` + + On `react-native-worklets` versions before 0.13.0, write `globalThis.navigator` instead of a bare `navigator`. Older versions of the Worklets babel plugin capture the main runtime's `navigator` object by closure instead of reading the one installed on the worklet runtime. + + If you create a device on the worklet runtime, beware that spontaneous device events are only delivered for devices created on the main JS runtime: - `device.lost` read on a worklet runtime returns a promise that never settles, unless the device is already lost at that point, in which case it resolves normally. - `uncapturederror` listeners registered on a device created on a worklet runtime never fire. diff --git a/packages/webgpu/src/install.ts b/packages/webgpu/src/install.ts index d5116aaa3..f7173c7ad 100644 --- a/packages/webgpu/src/install.ts +++ b/packages/webgpu/src/install.ts @@ -54,7 +54,7 @@ export const provideGPUForInstall = (gpu: GPU) => { * const work = () => { * "worklet"; * installWebGPU(); - * globalThis.navigator.gpu.requestAdapter().then((adapter) => { + * navigator.gpu.requestAdapter().then((adapter) => { * // ... * }); * }; @@ -62,12 +62,11 @@ export const provideGPUForInstall = (gpu: GPU) => { * * Known limitations: * - * - Read `navigator` through `globalThis.navigator`: the Worklets Babel - * plugin does not treat a bare `navigator` as a known global, so it would - * capture the main runtime's `navigator` object by closure instead of - * reading the one this function installed. Fixed upstream in - * react-native-reanimated#10364; the prefix becomes unnecessary on - * react-native-worklets versions that include it. + * - On react-native-worklets < 0.13.0, read `navigator` through + * `globalThis.navigator`: older versions of the Worklets Babel plugin do + * not treat a bare `navigator` as a known global, so they capture the main + * runtime's `navigator` object by closure instead of reading the one this + * function installed. * - Spontaneous events are main-runtime only: on a device created on a * worklet runtime, `device.lost` never settles (unless the device is * already lost when read) and `uncapturederror` listeners never fire.