{{ message }}
Repository navigation
Conversation
react-native-webview's injectedJavaScriptObject embeds the JSON in a JS template literal (iOS; Android from 13.13.1), so a double quote, backslash, newline, or backtick in any init param stops the Connect page from starting: the component never leaves its loader and never calls onLoadError. A double-quoted family name in appearance.variables.fontFamily is enough. Also pass the init params as an injectedJavaScriptBeforeContentLoaded script, replacing the empty placeholder. It defines window.ReactNativeWebView.injectedObjectJson() read-only, with the JSON in a string literal, so react-native-webview's definition can't replace it. Keep injectedJavaScriptObject: on Android, react-native-webview 13.6.0-13.13.0 serves it from a Java method that page scripts can't override and that never had this bug.
|
|
Contributor
Author
3 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
EmbeddedComponentnow passes the init params ininjectedJavaScriptBeforeContentLoaded, this replaces the empty'(function() {})();'placeholder.The script (
src/connect/injectedObjectScript.ts) defineswindow.ReactNativeWebView.injectedObjectJson(), which the Connect page already reads on startup.It returns the same JSON from a JS string literal and is read-only, so react-native-webview's own definition from
injectedJavaScriptObjectcan't replace it, whichever runs first.injectedJavaScriptObjectis still passed, unchanged.On Android, react-native-webview 13.6.0–13.13.0 serves
injectedObjectJson()from a Java method (RNCWebView.java#L286-L291, #L425-L426 @ v13.13.0) that page scripts can't override and that never had this bug. Expo SDK 50–52 pin versions in that range.Everywhere else the prop is only a fallback: if the script fails, the component behaves as on master.
The script is non-empty, so Android keeps re-injecting the object on each page start, which is what the placeholder was for (react-native-webview#3326).
No Connect page or public API change.
Motivation
If any init param (
appearance,locale,fonts, or a component prop) contains",\, a newline, or a backtick, the component stays on its loader and never callsonLoadError. An ordinary CSS font stack is enough.react-native-webview embeds the
injectedJavaScriptObjectJSON in a JS template literal,return `%@`;:The template literal turns
\"into"and\\into\, so the page's startupJSON.parsethrows. The Android WebView console shows:This is reported upstream as react-native-webview#3957 (iOS) and #3942 (Android).
The proposed fixes (#3958 and #3929) are still open.
Stripe SDK's default font avoids the bug only because it single-quotes family names (EmbeddedComponent.tsx#L902-L903).
Why fix it here: the
react-native-webviewpeer dependency is*(package.json#L106), so an upstream fix only reaches apps that upgrade; this change works with the versions apps already have.Repro: in
example-stripe-connect, set the Retro preset'sfontFamily(appearancePresets.ts#L171) to'"Courier New", Courier, monospace', choose Retro, and open Account onboarding.Testing
Manual:
example-stripe-connect(React Native 0.81.5) with react-native-webview 13.15.0 and 13.13.0, on an iOS 26.5 simulator and an Android 16 emulator (WebView 133): Retro preset → Account onboarding → Show Onboarding, then a screenshot after ~30 s.fontFamily"Courier New", Courier, monospaceonLoadErrorSyntaxErroraboveCourier(control)"Courier New", Courier, monospace"O'Reilly Sans", "Courier New", monospace13.13.0 is the last Android version with the Java method. Master already works there, so that column is a regression check. Without
injectedJavaScriptObject, the page there loads with the app's appearance missing, which is why the prop stays.Live appearance changes (iOS, Payouts). A new script makes react-native-webview re-install its user scripts, so I switched presets twice while the component was mounted: each change applied without a page reload, and "Sign in to edit payout destinations" still reached the app (
openAuthenticatedWebView).Automated:
injectedObjectScript.test.tsruns the script in a Nodevmcontext.${…}, U+2028/U+2029, and non-ASCII values round-trip exactly.EmbeddedComponent.test.tsx: the script carries the same init params asinjectedJavaScriptObject, including the default font. Both new tests fail on master.yarn typescript,yarn lint,yarn test,yarn test:package-types,cd example && yarn typescript, andyarn api-extractor:checkpass on Node 22.Documentation
Select one:
Added a CHANGELOG entry under Unreleased → Fixes.
AI assistance: I used Claude Code to trace the react-native-webview code paths, draft the change and tests, and drive the simulator and emulator runs. I reviewed the diff and the recordings.