From eda317bcb313cb0199f0c638458be24f83e09eba Mon Sep 17 00:00:00 2001 From: Grantmartin2002 <69131375+Grantmartin2002@users.noreply.github.com> Date: Tue, 25 Aug 2026 19:16:35 -0500 Subject: [PATCH] fix(v3/webview2): remove the native WebView2 loader and its embeds native_module_{386,amd64,arm64}.go embedded x86/, x64/ and arm64/ WebView2Loader.dll, but the root .gitignore *.dll rule kept those binaries out of every commit and therefore out of every published module zip. Because go mod vendor resolves embed patterns for all build configurations, ignoring GOOS, GOARCH and build tags, vendoring failed for every consumer on every OS, not just Windows builds. The native loader is the old path that loaded Microsoft's bootstrap DLL from memory via go-winloader. The pure Go loader has superseded it, so rather than ship the missing binaries, remove the native path entirely: delete native_module*.go and edge/create_env_native.go, drop the native_webview2loader build tag from the files that were gated against it, and drop the now-unused github.com/jchv/go-winloader dependency. Nothing referenced the embeds outside the tag, so default builds are unaffected. Passing -tags native_webview2loader still builds; the tag is now simply inert. Fixes #5782 Fixes #5376 --- v3/UNRELEASED_CHANGELOG.md | 2 + v3/go.mod | 1 - v3/go.sum | 3 - .../webview2/pkg/edge/create_env_go.go | 2 +- .../webview2/pkg/edge/create_env_native.go | 41 ----- .../webview2/webviewloader/env_create.go | 2 +- .../webviewloader/env_create_completed.go | 2 +- .../webviewloader/env_create_options.go | 2 +- .../webviewloader/find_dll_installed.go | 2 +- .../webview2/webviewloader/native_module.go | 173 ------------------ .../webviewloader/native_module_386.go | 8 - .../webviewloader/native_module_amd64.go | 8 - .../webviewloader/native_module_arm64.go | 8 - v3/internal/webview2/webviewloader/version.go | 2 +- 14 files changed, 8 insertions(+), 248 deletions(-) delete mode 100644 v3/internal/webview2/pkg/edge/create_env_native.go delete mode 100644 v3/internal/webview2/webviewloader/native_module.go delete mode 100644 v3/internal/webview2/webviewloader/native_module_386.go delete mode 100644 v3/internal/webview2/webviewloader/native_module_amd64.go delete mode 100644 v3/internal/webview2/webviewloader/native_module_arm64.go diff --git a/v3/UNRELEASED_CHANGELOG.md b/v3/UNRELEASED_CHANGELOG.md index 33638e7fc86..2840c09bebd 100644 --- a/v3/UNRELEASED_CHANGELOG.md +++ b/v3/UNRELEASED_CHANGELOG.md @@ -23,12 +23,14 @@ After processing, the content will be moved to the main changelog and this file ## Fixed +- Fix `go mod vendor` failing with `pattern arm64/WebView2Loader.dll: no matching files found` on every platform, by removing the embeds that referenced binaries never shipped in the module, fixing [#5782](https://github.com/wailsapp/wails/issues/5782) and [#5376](https://github.com/wailsapp/wails/issues/5376), in [PR](https://github.com/wailsapp/wails/pull/6031) by @Grantmartin2002 ## Deprecated ## Removed +- Remove native WebView2 loader support, superseded by the pure Go loader. This drops the embedded `WebView2Loader.dll` binaries and the `github.com/jchv/go-winloader` dependency. The `native_webview2loader` build tag is still accepted and no longer errors, but has no effect on v3 builds, in [PR](https://github.com/wailsapp/wails/pull/6031) by @Grantmartin2002 ## Security diff --git a/v3/go.mod b/v3/go.mod index c2e637ed48c..832db889888 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -115,7 +115,6 @@ require ( github.com/huandu/xstrings v1.5.0 // indirect github.com/jaypipes/pcidb v1.1.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 github.com/joho/godotenv v1.5.1 // indirect github.com/kevinburke/ssh_config v1.4.0 // indirect github.com/klauspost/compress v1.18.3 // indirect diff --git a/v3/go.sum b/v3/go.sum index f466e9964b6..cdb4f5eac2c 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -222,8 +222,6 @@ github.com/jaypipes/pcidb v1.1.1 h1:QmPhpsbmmnCwZmHeYAATxEaoRuiMAJusKYkUncMC0ro= github.com/jaypipes/pcidb v1.1.1/go.mod h1:x27LT2krrUgjf875KxQXKB0Ha/YXLdZRVmw6hH0G7g8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= @@ -428,7 +426,6 @@ golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/v3/internal/webview2/pkg/edge/create_env_go.go b/v3/internal/webview2/pkg/edge/create_env_go.go index 252edc3e256..3bd5c1303f5 100644 --- a/v3/internal/webview2/pkg/edge/create_env_go.go +++ b/v3/internal/webview2/pkg/edge/create_env_go.go @@ -1,4 +1,4 @@ -//go:build windows && !native_webview2loader +//go:build windows package edge diff --git a/v3/internal/webview2/pkg/edge/create_env_native.go b/v3/internal/webview2/pkg/edge/create_env_native.go deleted file mode 100644 index 57259dd0ea9..00000000000 --- a/v3/internal/webview2/pkg/edge/create_env_native.go +++ /dev/null @@ -1,41 +0,0 @@ -//go:build windows && native_webview2loader - -package edge - -import ( - "fmt" - "syscall" - "unsafe" - - "github.com/wailsapp/wails/v3/internal/webview2/webviewloader" - - "golang.org/x/sys/windows" -) - -func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error { - browserPathPtr, err := windows.UTF16PtrFromString(browserExecutableFolder) - if err != nil { - return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", browserExecutableFolder, err) - } - - userPathPtr, err := windows.UTF16PtrFromString(userDataFolder) - if err != nil { - return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", userDataFolder, err) - } - - hr, err := webviewloader.CreateCoreWebView2EnvironmentWithOptions( - browserPathPtr, - userPathPtr, - uintptr(unsafe.Pointer(environmentCompletedHandle)), - additionalBrowserArgs, - ) - if err != nil { - return fmt.Errorf("Error calling CreateCoreWebView2EnvironmentWithOptions: %v", err) - } - - if hr != 0 { - return syscall.Errno(hr) - } - - return nil -} diff --git a/v3/internal/webview2/webviewloader/env_create.go b/v3/internal/webview2/webviewloader/env_create.go index 438161b9c20..1ebb02c0a7e 100644 --- a/v3/internal/webview2/webviewloader/env_create.go +++ b/v3/internal/webview2/webviewloader/env_create.go @@ -1,4 +1,4 @@ -//go:build windows && !native_webview2loader +//go:build windows package webviewloader diff --git a/v3/internal/webview2/webviewloader/env_create_completed.go b/v3/internal/webview2/webviewloader/env_create_completed.go index 2ade02465a7..9c8efa8e0c4 100644 --- a/v3/internal/webview2/webviewloader/env_create_completed.go +++ b/v3/internal/webview2/webviewloader/env_create_completed.go @@ -1,4 +1,4 @@ -//go:build windows && !native_webview2loader +//go:build windows package webviewloader diff --git a/v3/internal/webview2/webviewloader/env_create_options.go b/v3/internal/webview2/webviewloader/env_create_options.go index b42b2bb222f..f4030838405 100644 --- a/v3/internal/webview2/webviewloader/env_create_options.go +++ b/v3/internal/webview2/webviewloader/env_create_options.go @@ -1,4 +1,4 @@ -//go:build windows && !native_webview2loader +//go:build windows package webviewloader diff --git a/v3/internal/webview2/webviewloader/find_dll_installed.go b/v3/internal/webview2/webviewloader/find_dll_installed.go index 7ee171b2ad1..dd88757a19e 100644 --- a/v3/internal/webview2/webviewloader/find_dll_installed.go +++ b/v3/internal/webview2/webviewloader/find_dll_installed.go @@ -1,4 +1,4 @@ -//go:build windows && !native_webview2loader +//go:build windows package webviewloader diff --git a/v3/internal/webview2/webviewloader/native_module.go b/v3/internal/webview2/webviewloader/native_module.go deleted file mode 100644 index 3e02fe985e7..00000000000 --- a/v3/internal/webview2/webviewloader/native_module.go +++ /dev/null @@ -1,173 +0,0 @@ -//go:build windows && native_webview2loader - -package webviewloader - -import ( - "errors" - "fmt" - "os" - "sync" - "unsafe" - - "github.com/jchv/go-winloader" - - "golang.org/x/sys/windows" -) - -func init() { - preventEnvAndRegistryOverrides(nil, nil, "") -} - -var ( - memOnce sync.Once - memModule winloader.Module - memCreate winloader.Proc - memCompareBrowserVersions winloader.Proc - memGetAvailableCoreWebView2BrowserVersionString winloader.Proc - memErr error -) - -const ( - // https://referencesource.microsoft.com/#system.web/Util/hresults.cs,20 - E_FILENOTFOUND = 0x80070002 -) - -// CompareBrowserVersions will compare the 2 given versions and return: -// -// Less than zero: v1 < v2 -// zero: v1 == v2 -// Greater than zero: v1 > v2 -func CompareBrowserVersions(v1 string, v2 string) (int, error) { - _v1, err := windows.UTF16PtrFromString(v1) - if err != nil { - return 0, err - } - _v2, err := windows.UTF16PtrFromString(v2) - if err != nil { - return 0, err - } - - err = loadFromMemory() - if err != nil { - return 0, err - } - - var result int32 - _, _, err = memCompareBrowserVersions.Call( - uint64(uintptr(unsafe.Pointer(_v1))), - uint64(uintptr(unsafe.Pointer(_v2))), - uint64(uintptr(unsafe.Pointer(&result)))) - - if err != windows.ERROR_SUCCESS { - return 0, err - } - return int(result), nil -} - -// GetAvailableCoreWebView2BrowserVersionString returns version of the webview2 runtime. -// If path is empty, it will try to find installed webview2 is the system. -// If there is no version installed, a blank string is returned. -func GetAvailableCoreWebView2BrowserVersionString(path string) (string, error) { - if path != "" { - // The default implementation fails if CGO and a fixed browser path is used. It's caused by the go-winloader - // which loads the native DLL from memory. - // Use the new GoWebView2Loader in this case, in the future we will make GoWebView2Loader - // feature-complete and remove the use of the native DLL and go-winloader. - version, err := goGetAvailableCoreWebView2BrowserVersionString(path) - if errors.Is(err, errNoClientDLLFound) { - // WebView2 is not found - return "", nil - } else if err != nil { - return "", err - } - - return version, nil - } - - err := loadFromMemory() - if err != nil { - return "", err - } - - var browserPath *uint16 = nil - if path != "" { - browserPath, err = windows.UTF16PtrFromString(path) - if err != nil { - return "", fmt.Errorf("error calling UTF16PtrFromString for %s: %v", path, err) - } - } - - preventEnvAndRegistryOverrides(browserPath, nil, "") - var result *uint16 - res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call( - uint64(uintptr(unsafe.Pointer(browserPath))), - uint64(uintptr(unsafe.Pointer(&result)))) - - if res != 0 { - if res == E_FILENOTFOUND { - // WebView2 is not installed - return "", nil - } - - return "", fmt.Errorf("Unable to call GetAvailableCoreWebView2BrowserVersionString (%x): %w", res, err) - } - - version := windows.UTF16PtrToString(result) - windows.CoTaskMemFree(unsafe.Pointer(result)) - return version, nil -} - -// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and -// call the CreateCoreWebView2EnvironmentWithOptions routine. -func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentCompletedHandle uintptr, additionalBrowserArgs string) (uintptr, error) { - err := loadFromMemory() - if err != nil { - return 0, err - } - - preventEnvAndRegistryOverrides(browserExecutableFolder, userDataFolder, additionalBrowserArgs) - res, _, _ := memCreate.Call( - uint64(uintptr(unsafe.Pointer(browserExecutableFolder))), - uint64(uintptr(unsafe.Pointer(userDataFolder))), - 0, - uint64(environmentCompletedHandle), - ) - return uintptr(res), nil -} - -func loadFromMemory() error { - var err error - // DLL is not available natively. Try loading embedded copy. - memOnce.Do(func() { - memModule, memErr = winloader.LoadFromMemory(WebView2Loader) - if memErr != nil { - err = fmt.Errorf("Unable to load WebView2Loader.dll from memory: %w", memErr) - return - } - memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions") - memCompareBrowserVersions = memModule.Proc("CompareBrowserVersions") - memGetAvailableCoreWebView2BrowserVersionString = memModule.Proc("GetAvailableCoreWebView2BrowserVersionString") - }) - return err -} - -func preventEnvAndRegistryOverrides(browserFolder, userDataFolder *uint16, additionalBrowserArgs string) { - // Setting these env variables to empty string also prevents registry overrides because webview2loader - // checks for existence and not for empty value - os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "") - - // Set these overrides to the values or empty to prevent registry and external env overrides - os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", additionalBrowserArgs) - os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0") - os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", windows.UTF16PtrToString(browserFolder)) - os.Setenv("WEBVIEW2_USER_DATA_FOLDER", windows.UTF16PtrToString(userDataFolder)) -} - -func goGetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) { - clientPath, err := findEmbeddedClientDll(browserExecutableFolder) - if err != nil { - return "", err - } - - return findEmbeddedBrowserVersion(clientPath) -} diff --git a/v3/internal/webview2/webviewloader/native_module_386.go b/v3/internal/webview2/webviewloader/native_module_386.go deleted file mode 100644 index e4ff44ff312..00000000000 --- a/v3/internal/webview2/webviewloader/native_module_386.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build windows && native_webview2loader - -package webviewloader - -import _ "embed" - -//go:embed x86/WebView2Loader.dll -var WebView2Loader []byte diff --git a/v3/internal/webview2/webviewloader/native_module_amd64.go b/v3/internal/webview2/webviewloader/native_module_amd64.go deleted file mode 100644 index 27423ae8aa8..00000000000 --- a/v3/internal/webview2/webviewloader/native_module_amd64.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build windows && native_webview2loader - -package webviewloader - -import _ "embed" - -//go:embed x64/WebView2Loader.dll -var WebView2Loader []byte diff --git a/v3/internal/webview2/webviewloader/native_module_arm64.go b/v3/internal/webview2/webviewloader/native_module_arm64.go deleted file mode 100644 index bba6a88cb1e..00000000000 --- a/v3/internal/webview2/webviewloader/native_module_arm64.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build windows && native_webview2loader - -package webviewloader - -import _ "embed" - -//go:embed arm64/WebView2Loader.dll -var WebView2Loader []byte diff --git a/v3/internal/webview2/webviewloader/version.go b/v3/internal/webview2/webviewloader/version.go index 9e408752536..25edf4558ad 100644 --- a/v3/internal/webview2/webviewloader/version.go +++ b/v3/internal/webview2/webviewloader/version.go @@ -1,4 +1,4 @@ -//go:build windows && !native_webview2loader +//go:build windows package webviewloader