Skip to content

[Bug]: WebView2 COM events silently fail with MSVC /O2 or /Ox optimization #1642

@mateusz28011

Description

@mateusz28011

Detailed steps on how to reproduce the bug

  1. Create a JUCE plugin with WebBrowserComponent using the WebView2 backend and a resource provider (getResourceProviderRoot() / embedded frontend mode)
  2. Build Release on Windows with MSVC (tested with v14.44, VS 2022 BuildTools)
  3. The default juce_recommended_config_flags applies /Ox in Release
  4. 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:

  • CreateCoreWebView2EnvironmentWithOptionsS_OK
  • CreateCoreWebView2ControllerS_OK
  • AddWebResourceRequestedFilter("*")S_OK
  • Navigate(url)S_OK
  • get_IsVisibleTRUE, 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions