SIGN IN SIGN UP

Don't evaluate `__DEV__` or `Reanimated` at module scope (#4375)

## Description

Importing a v3 module currently executes environment-dependent code
during module evaluation in two places. That's harmless under Metro
(where `__DEV__` is a compile-time constant), but breaks when modules
are evaluated in environments where `__DEV__` is a runtime global (e.g.
web bundlers, where `sideEffects`-aware optimization can evaluate leaf
modules before any entry-point setup runs):

- `propsWhiteList` read `__DEV__` at module scope to strip `testID` from
the native-prop whitelists in production. The filter is now applied
lazily (idempotent `applyProductionTestIDFilter()`), called on first
`prepareConfigForNativeSide`. Same observable behavior, but the decision
moves from import time to first use, which also makes it testable.
- `useReanimatedEventHandler` called `Reanimated?.makeMutable()` at
module scope to create `lastUpdateEventMap`. The map is now created
lazily on first use. Worklet-capture safety: the event-handler worklet
captures the initialized map obtained on the JS thread during render,
and the cleanup worklet receives the map as a `runOnUI` argument.
Capturing the lazy module binding directly would snapshot `undefined` at
workletization time.

To keep the pattern from coming back, a lint rule (scoped to
`src/v3/**`, `src/web/**`, and root `src/*.ts`) now errors on any
`__DEV__` read outside a function body.

## Test plan

- `yarn ts-check` clean; `yarn test` 106/106; `yarn lint:js` 0 errors
- New `propsWhiteList.test.ts`: `testID` delivered in dev, stripped in
production (`__DEV__ = false`)
- Lint rule verified on fixtures: flags top-level reads, passes
function/arrow/method reads
- Verified on iOS simulator (expo-example, Reanimated worklet path): pan
with `changeX`/`changeY` deltas (map-backed change-calculator context),
unmount cleanup (`runOnUI` with map argument), remount with a fresh
handler
M
Michał Bert committed
a0c30953699825d8e69071aea502a6b7f3be7c3b
Parent: d63bc83
Committed by GitHub <noreply@github.com> on 8/5/2026, 7:23:21 AM