Install the JS bridge at document start on every desktop backend - #61
Merged
Conversation
The desktop bridge object was injected from Compose after load, gated on a LoadingState/lastLoadedUrl change derived from a 120 ms poller. A navigation that starts and finishes inside one tick, or that keeps the same document URL (loadHtml without baseUrl stays on about:blank), produced no emission, so window.kmpJsBridge was never re-injected. Page startup scripts never saw it either, since injection only happened once the load had finished. Windows already worked around this with a hardcoded document-start shim. The JS half of the bridge now lives in one place (jsBridgeObjectScript) and is handed to nativeCreate, which installs it as a document-start user script on WebKit2GTK, WKWebView and WebView2 — so it exists before the first page statement of every document, honours a custom jsBridgeName on all three backends, and no longer depends on poller timing. Suite cases B10/B11 cover it: calling the bridge from an inline script, and three successive loads that keep the same URL. Both fail against the previous behaviour (verified on macOS) and pass with the fix (70/70). Fixes #60
Android / iOS / WasmJs still inject the bridge after load, so B10/B11 report Skipped there instead of Failed — the catalog stays identical across platforms and the matrix stays honest.
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.
Fixes #60.
Problem
The desktop
window.kmpJsBridgeobject was injected from Compose after load (WebView.kt), gated on aLoadingState.Finished/lastLoadedUrlchange — and on desktop both signals come from a 120 ms poller, not from real navigation callbacks like Android (onPageFinished) and iOS (nav delegate).Two failure modes followed:
Finishedis adata object, sosnapshotFlowconflates it. A load that starts and finishes inside one tick (in-memory HTML,data:URLs, cached pages) or that keeps the same document URL (loadHtmlwithoutbaseUrlstays onabout:blank) produced no emission → the bridge was never re-injected into the new document.DOMContentLoaded, framework boot) sawundefined.Windows already worked around this with a document-start shim that hardcoded
kmpJsBridge; macOS and Linux only got thewindow.ipctransport shim.The existing suite could not catch any of this: every load used a unique
baseUrl(https://suite.local/<marker>), which always changeslastLoadedUrl.Fix
jsBridgeObjectScript(name, postMessageBody)incommonMain, used both byIWebView.injectJsBridge()and by the desktop factory.WebViewFactoryParamcarries thejsBridgeName; the desktop factory builds the bootstrap and passes it tonativeCreate, which installs it as a document-start user script on all three backends (WKUserScript,webkit_user_content_manager_add_script,AddScriptToExecuteOnDocumentCreated), all frames.WebViewJsBridge(jsBridgeName = …)now works on every desktop backend.typeof window.<name> === 'undefined').Tests
New suite cases, both red against the previous behaviour and green with the fix (verified locally on macOS by rebuilding the dylib with the injection neutralised):
B10B11baseUrl = null)Before:
passed=68 failed=2—B10: bridge absent while the document was parsing,B11: timed out.After:
passed=70 failed=0 allGreen=true.Plus 3 unit tests for
jsBridgeObjectScript(custom name,postMessagerouting, callback contract) in the sharedcommonTestsuite.CI runs the visual suite on Linux (WebKit2GTK), Windows (WebView2) and macOS (WKWebView) with freshly built natives — the JNI signature changed, so all three are rebuilt from source here.