fix(new-arch): align TurboModule openPicker signature across iOS, Android, and JS#967
fix(new-arch): align TurboModule openPicker signature across iOS, Android, and JS#967idanlevi1 wants to merge 2 commits into
Conversation
…roid, and JS Under React Native's new architecture, the TurboModule runtime enforces strict argument-count parity between the JS-side spec, the platform native module, and every JS caller. `react-native-date-picker` currently has three sources of truth for `openPicker` and they disagree: | Layer | Args | |-----------------------------------------------|---------------| | iOS native (`ios/RNDatePickerManager.mm`) | 3 (uses cbs) | | Android native newarch (`DatePickerModule`) | 1 | | Codegen spec (`src/fabric/NativeRNDatePicker.ts`) | 1 | | JS caller iOS (`src/modal.js`) | 3 | | JS caller Android (`src/modal.js`) | 1 | So one of the two platforms is always wrong: - With the spec at 1 arg, the iOS caller's 3-arg invocation is over by two (RN currently permits this, but it is undocumented behaviour and fails strict tooling). - If a consumer patches the spec to 3 args to match iOS (a common workaround once they hit `TurboModule method "openPicker" called with 1 arguments (expected argument count: 3)`), the Android JS caller starts crashing on every modal open. This PR makes all five layers agree on 3 args: - `src/fabric/NativeRNDatePicker.ts` — spec now declares `openPicker(props, onConfirm, onCancel)`. - `android/src/newarch/java/.../DatePickerModule.java` — accepts `Callback onConfirm, Callback onCancel` and ignores them; Android continues to deliver confirm/cancel via the existing `RCTDeviceEventEmitter` flow. - `src/modal.js` — Android branch now passes two no-op callbacks so the 3-arg signature is honoured on both platforms. iOS behaviour is unchanged at runtime (its native side already takes 3 args and uses them). Android behaviour is unchanged at runtime (the callbacks are unused; events still flow via the emitter listeners registered in `useModal`). Encountered downstream in a React Native 0.85 + new-arch banking app where opening any modal date picker (transaction filter date range, loan payment day) on Android crashed with the strict arg-count error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9337c44 to
574a2f9
Compare
|
Pushed lint fix (yarn lint --fix). Two pre-existing prettier issues in The iOS build job is failing on a CI-infrastructure issue, not a code one: the runner uses Ruby 2.7.5 but the current CocoaPods install requires |
`pr.yml` is triggered by `pull_request_target`, which by default runs in
the base-branch (master) context. Most workflows already override the
checkout ref to the PR head:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
`lint.yml` was missing that override, so lint was always run against
master's source rather than the PR head — meaning lint failures on the
PR could not be fixed by the PR, and prettier issues already in master
permanently broke every contributor's lint check.
Mirror the existing pattern from build-android.yml / build-ios.yml /
test-android-*.yml.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Lint failures are a CI config bug, not a code issue:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}…but Pushed an additional commit mirroring the existing pattern from the other workflows. Same fix probably applies to For the iOS Build job, that's a separate runtime/CI issue (Ruby 2.7.5 on the macOS runner can't install the latest CocoaPods because |
|
Confirming: my CI fixes can't pass these checks from a PR. So this needs a maintainer action — either:
Happy to split the CI-config fix out into a separate PR against master so it lands cleanly first, then this one can be re-run on the fixed CI — but I'll stop pushing further commits to this branch until you've decided which path you'd prefer. iOS Build is still the separate Ruby/CocoaPods issue ( |
|
Opened a small parallel PR (#968) with just the two CI-hygiene fixes needed to unblock the lint check on this repo — auto-fixing the pre-existing prettier issues in master's |
Problem
Under React Native's new architecture, the TurboModule runtime enforces strict argument-count parity between the codegen spec, the platform native module, and every JS caller. `openPicker` currently disagrees across five places:
So one of the two platforms is always wrong:
Repro for the consumer case: RN 0.85 + new architecture, Android — open any modal date picker (`modal` mode in the component) → strict arg-count crash.
Fix
Make all five layers agree on 3 args:
iOS behaviour is unchanged at runtime (native already takes 3 args and uses them). Android behaviour is unchanged at runtime (the callbacks are unused; events still flow via the emitter listeners registered in `useModal`).
Why this direction (3 args, not 1)
The alternative (move iOS off callbacks onto the emitter pattern so the spec could shrink to 1 arg) is the cleaner long-term refactor — and looks like the direction `upstream/unify-native-api` is heading. But that branch is still WIP and a much bigger change. The 3-arg alignment in this PR is the minimum diff that unblocks new-arch consumers today without breaking anything; the deeper unification can land on top later.
Test plan
Happy to add a test in `example` if desired.