Detailed steps on how to reproduce the bug
- Create a JUCE plugin with
WebBrowserComponent using the WebView2 backend and a resource provider (getResourceProviderRoot() / embedded frontend mode)
- Build Release on Windows with MSVC (tested with v14.44, VS 2022 BuildTools)
- The default
juce_recommended_config_flags applies /Ox in Release
- Launch the Standalone — WebView2 shows a white/blank screen
The WebView2 controller is created successfully, Navigate() returns S_OK, but no events fire: NavigationStarting, NavigationCompleted, and WebResourceRequested callbacks are never invoked. ExecuteScript returns null. The page source remains about:blank after Navigate().
Replacing /Ox or /O2 with /O1 in Release compile options fixes the issue. The difference between /O1 and /O2 is /Oi (intrinsics) and /Ot (favor speed) — one or both of these flags appear to corrupt WRL Callback<> COM vtable dispatch across the WebView2 process boundary.
Debug vs Release behavior
The exact same code path works perfectly in Debug and fails silently in Release:
| Build config |
Optimization |
Result |
Debug (DEV_MODE=OFF, embedded frontend) |
/Od |
Works — all events fire, frontend loads |
Release with /Od forced |
/Od |
Works |
Release with /O1 |
/O1 |
Works |
Release with default juce_recommended_config_flags |
/Ox |
Fails — white screen, zero events |
Release with /O2 manually |
/O2 |
Fails — same symptoms |
This rules out any code logic issue and points specifically to MSVC optimization breaking the WRL Callback<> COM vtable dispatch used in juce_WebBrowserComponent_windows.cpp.
Minimal workaround in CMakeLists.txt
Do not link juce::juce_recommended_config_flags on Windows and manually supply /O1 /MP /EHsc:
target_link_libraries(SharedCode INTERFACE
juce::juce_audio_utils
juce::juce_recommended_warning_flags
)
if(WIN32)
target_compile_options(SharedCode INTERFACE
$<$<CONFIG:Debug>:/Od>
$<$<CONFIG:Release>:/O1>
/MP /EHsc)
else()
target_link_libraries(SharedCode INTERFACE
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags)
endif()
Environment
- JUCE: 8.0.12 (also verified on
develop branch — same /Ox in JUCEHelperTargets.cmake:123)
- WebView2 SDK: tested with both 1.0.1901.177 and 1.0.3856.49 (latest) — same result
- MSVC: 14.44.35207 (VS 2022 BuildTools)
- Edge Runtime: 146.0.3856.97
- Linking:
JUCE_USE_WIN_WEBVIEW2_WITH_STATIC_LINKING=1
Diagnostic findings
Through extensive logging added to juce_WebBrowserComponent_windows.cpp:
CreateCoreWebView2EnvironmentWithOptions → S_OK
CreateCoreWebView2Controller → S_OK
AddWebResourceRequestedFilter("*") → S_OK
Navigate(url) → S_OK
get_IsVisible → TRUE, bounds are correct
get_BrowserProcessId → valid PID
get_Source after Navigate → still about:blank
- Zero
NavigationStarting / WebResourceRequested / NavigationCompleted events
- Debug builds (
/Od) work perfectly with the exact same code path
What is the expected behaviour?
Navigate() should trigger NavigationStarting and WebResourceRequested events regardless of MSVC optimization level. The resource provider should serve embedded frontend files and the WebView should render content, not a blank white screen.
Operating systems
Windows
What versions of the operating systems?
Windows 11 Home 10.0.26200
Architectures
x86_64
Plug-in formats (if applicable)
Standalone, VST3
Plug-in host applications (DAWs) (if applicable)
N/A (Standalone)
Testing on the develop branch
Confirmed on develop branch (commit 28706b9811 — "Windows Clang: Fix a bug querying CPU information"). Same white screen with /Ox, works with /O1.
Detailed steps on how to reproduce the bug
WebBrowserComponentusing the WebView2 backend and a resource provider (getResourceProviderRoot()/ embedded frontend mode)juce_recommended_config_flagsapplies/Oxin ReleaseThe WebView2 controller is created successfully,
Navigate()returnsS_OK, but no events fire:NavigationStarting,NavigationCompleted, andWebResourceRequestedcallbacks are never invoked.ExecuteScriptreturnsnull. The page source remainsabout:blankafterNavigate().Replacing
/Oxor/O2with/O1in Release compile options fixes the issue. The difference between/O1and/O2is/Oi(intrinsics) and/Ot(favor speed) — one or both of these flags appear to corrupt WRLCallback<>COM vtable dispatch across the WebView2 process boundary.Debug vs Release behavior
The exact same code path works perfectly in Debug and fails silently in Release:
DEV_MODE=OFF, embedded frontend)/Od/Odforced/Od/O1/O1juce_recommended_config_flags/Ox/O2manually/O2This rules out any code logic issue and points specifically to MSVC optimization breaking the WRL
Callback<>COM vtable dispatch used injuce_WebBrowserComponent_windows.cpp.Minimal workaround in CMakeLists.txt
Do not link
juce::juce_recommended_config_flagson Windows and manually supply/O1 /MP /EHsc:Environment
developbranch — same/OxinJUCEHelperTargets.cmake:123)JUCE_USE_WIN_WEBVIEW2_WITH_STATIC_LINKING=1Diagnostic findings
Through extensive logging added to
juce_WebBrowserComponent_windows.cpp:CreateCoreWebView2EnvironmentWithOptions→S_OKCreateCoreWebView2Controller→S_OKAddWebResourceRequestedFilter("*")→S_OKNavigate(url)→S_OKget_IsVisible→TRUE, bounds are correctget_BrowserProcessId→ valid PIDget_Sourceafter Navigate → stillabout:blankNavigationStarting/WebResourceRequested/NavigationCompletedevents/Od) work perfectly with the exact same code pathWhat is the expected behaviour?
Navigate()should triggerNavigationStartingandWebResourceRequestedevents regardless of MSVC optimization level. The resource provider should serve embedded frontend files and the WebView should render content, not a blank white screen.Operating systems
Windows
What versions of the operating systems?
Windows 11 Home 10.0.26200
Architectures
x86_64
Plug-in formats (if applicable)
Standalone, VST3
Plug-in host applications (DAWs) (if applicable)
N/A (Standalone)
Testing on the develop branch
Confirmed on
developbranch (commit28706b9811— "Windows Clang: Fix a bug querying CPU information"). Same white screen with/Ox, works with/O1.