You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gtk+3-3.24.49 and devel (⚠️same here, repology says latest version is 4.18 (!), looks like I am using a dead distro, sadge)
Void Linux 6.12
Note: Most of the text of this issue is written by Gemini 2.5 Pro with the context of my debugging attempts for the last 2 days + all the code of assetserver of wails' master branch.
Problem Description:
In wails dev mode, when frontend:dev:serverUrl is configured to point to a Vite development server, WebAssembly (.wasm) files fetched by wasm-bindgen's JavaScript glue are ultimately served to the WebKit webview via the wails:// protocol without the necessary Content-Type: application/wasm header. This occurs even if Vite serves the .wasm file with the correct Content-Type to Wails's ExternalAssetHandler proxy.
The absence of the correct Content-Type header on the response received by the webview causes WebAssembly.instantiateStreaming to fail. While wasm-bindgen's glue code may fall back to WebAssembly.instantiate(ArrayBuffer), this often results in an incompletely initialized WASM instance where standard WebAssembly JavaScript APIs, particularly access to WebAssembly.Memory (and thus wasm_bindgen::memory() from Rust), are non-functional.
Observed Flow in wails dev:
* The Wails webview requests the initial index.html and subsequently src/lib/wasm.ts and src/wasm-generated/pkg/app.js. Wails's AssetHandler proxies these requests to Vite's HTTP dev server. The content is served back to the webview, but the import.meta.url context within these loaded scripts becomes wails://wails.localhost:34115/src/....
* The app.js (glue) attempts to fetch app_bg.wasm using a URL resolved to wails://wails.localhost:34115/src/wasm-generated/pkg/app_bg.wasm.
* Wails's AssetHandler intercepts this wails:// request for app_bg.wasm.
* Its ExternalAssetHandler component then successfully fetches http://localhost:34115/src/wasm-generated/pkg/app_bg.wasm from Vite. Vite serves this with Content-Type: application/wasm to Wails's proxy.
* Wails's AssetHandler then serves the received .wasm binary content back to the webview in response to the wails://.../app_bg.wasm request.
* Crucially, inspecting this final response to the webview (e.g., via WebKit Network DevTools) shows "No response headers" or that the Content-Type header from Vite's response was not propagated.
* The wasm-bindgen JS glue logs a warning: "WebAssembly.instantiateStreaming failed because your server does not serve Wasm with application/wasm MIME type."
* Subsequent attempts to use wasm_bindgen::memory() from within Rust fail, indicating the WebAssembly.Memory object was not correctly linked or initialized.
To Reproduce
Setup:
* Wails v2 project with Vite frontend (for Svelte/TS)
* Rust/WASM module built with wasm-pack --target web --out-dir frontend/src/some-dir/pkg.
* Vite configured with vite-plugin-wasm, vite-plugin-top-level-await, and optimizeDeps.exclude for the WASM package.
* Wails wails.json has frontend:dev:serverUrl pointing to Vite's HTTP dev server (e.g., http://localhost:34115).
* Frontend JavaScript (e.g., in src/lib/wasm.ts) statically imports the wasm-bindgen JS glue (e.g., import initApp from '../wasm-generated/pkg/app.js';).
* initApp() is called, which then (internally, via new URL('./app_bg.wasm', import.meta.url)) attempts to fetch the companion .wasm file.
Expected behaviour
Wails's ExternalAssetHandler, when proxying a response from the Vite dev server (which includes a Content-Type: application/wasm header for .wasm files), should preserve or correctly set this Content-Type header on the response it ultimately sends to the webview, even when serving via the wails:// scheme. This would allow WebAssembly.instantiateStreaming to succeed and ensure full WASM API functionality.
Screenshots
Attempted Fixes
The location of the bug hasn't been pinpointed exactly so for any other wails devs who want to use WASM, here is the workaround I am considering: inlining WASM binaryor using AssetServer.Middleware.
I briefly got inlined WASM to work with functional WASM browser APIs so this one is confirmed to work but I originally ruled against it because it looked too brittle.
1. Manual WASM Inlining (JS Glue Modification)
Approach:
The .wasm binary is Base64 encoded.
The wasm-bindgen-generated JavaScript glue file (e.g., log_engine.js) is modified by a build script (e.g., a Node.js or shell script).
This modification involves:
Embedding the Base64 string and a base64ToArrayBuffer helper function within the JS glue.
Surgically altering wasm-bindgen's primary initialization function (typically the default export, async function __wbg_init(module_or_path)) to bypass its internal fetch logic and instead use the embedded ArrayBuffer (e.g., by setting module_or_path = WASM_BINARY_BUFFER; before __wbg_load is called).
This self-contained, inlined JS glue file is then imported and initialized by the application.
Status & Outcome:
This approach successfully bypasses the network fetch for the .wasm file, thereby avoiding the wails:// Content-Type issue for the binary itself.
When implemented carefully to ensure wasm-bindgen's internal state (particularly wasm.memory which wasm_bindgen::memory() relies on) is correctly initialized after instantiating from the buffer, this method has been shown to result in functional WebAssembly browser APIs.
Drawbacks & Considerations for Developers:
Complexity of Patching: Correctly and robustly modifying wasm-bindgen's generated JS glue is non-trivial. The glue code is auto-generated and its internal structure can change between wasm-bindgen versions, making such patches fragile and hard to maintain.
Increased JS Bundle Size: Embedding the WASM binary (even Base64 encoded) directly into the JavaScript significantly increases the size of that JS file.
Build Process Overhead: Requires an additional, custom build step to perform the encoding and patching.
Debugging: Source mapping for the original Rust code might become more challenging with a heavily modified JS glue.
Note for Wails Developers: This workaround highlights that if the WASM binary can be delivered to WebAssembly.instantiate as an ArrayBuffer without relying on wails:// for fetching the binary itself with correct headers, the core WASM instantiation and API linkage can work. The difficulty lies in achieving this without breaking wasm-bindgen's own setup logic.
2. Wails AssetServer.Middleware (Theoretical, Untested for this Specific WASM Case) Revised Assessment → Likely Ineffective for API Access Issue): Since the middleware operates on the Go http.ResponseWriter before this final translation to the webview for wails:// requests, if the Wails-to-webview interface or the webview itself is the point of failure for header recognition for custom schemes, the middleware alone won't fix the WASM API access issue. Therefore, this middleware approach is now considered unlikely to be a complete solution for enabling full WASM API functionality in the current wails dev environment.
System Details
# System
WARNING: failed to read int from file: open /sys/devices/system/cpu/cpu0/online: no such file or directory
┌─────────────────────────────────────────────────────────────────────────────────┐
| OS | Void || Version | Unknown || ID | void || Go Version | go1.23.4 || Platform | linux || Architecture | amd64 || CPU | Intel(R) Pentium(R) Silver N5000 CPU @ 1.10GHz || GPU | GeminiLake [UHD Graphics 605] (Intel Corporation) - Driver: i915 || Memory | 8GB |
└─────────────────────────────────────────────────────────────────────────────────┘
# Dependencies
┌──────────────────────────────────────────────┐
| Dependency | Package Name | Status | Version |||
└──────────────────────────────────────────────┘
# Diagnosis
SUCCESS Your system is ready for Wails development!
Additional context
Possible Root Causes for Missing Content-Type on wails:// Response:
The issue where the Content-Type: application/wasm header (received from the Vite dev server by Wails's ExternalAssetHandler) is not present on the final response to the WebKitGTK webview for wails:// scheme requests appears to stem from the interaction between Wails's Go code and the underlying WebKitGTK/libsoup APIs for custom scheme handling.
Issue in Wails's CGO Bridging or WebKitGTK/libsoup API Usage for Custom Schemes (Linux):
Wails's ExternalAssetHandler uses httputil.ReverseProxy, which should preserve headers from the upstream Vite server (including Content-Type: application/wasm) onto the Go http.ResponseWriter it's given.
This ResponseWriter is a Wails wrapper (webview.ResponseWriter) which, on Linux, is implemented in v2/pkg/assetserver/webview/responsewriter_linux.go.
The WriteHeader method in responsewriter_linux.go calls webkit_uri_scheme_request_finish (defined in v2/pkg/assetserver/webview/webkit2_36+.go).
The webkit_uri_scheme_request_finish function explicitly attempts to set the Content-Type and all other HTTP headers on the WebKitURISchemeResponse using CGO calls to WebKitGTK/libsoup functions:
C.soup_message_headers_append(hdrs, cName, cValue) followed by C.webkit_uri_scheme_response_set_http_headers(resp, hdrs).
The Problem: Despite these explicit attempts by Wails's Go code to set the headers, the WebKitGTK DevTools show "No response headers" for the .wasm file served via wails://. This points to a potential issue in:
The CGO marshalling/unmarshalling of header data between Go and C.
The specific way these WebKitGTK/libsoup C functions (webkit_uri_scheme_response_set_content_type, webkit_uri_scheme_response_set_http_headers, soup_message_headers_append) are being used by Wails for custom scheme responses.
A bug or limitation within WebKitGTK/libsoup itself when handling headers (especially Content-Type for binary types like application/wasm) for requests made over custom URL schemes (like wails://). Historical Wails issues with other media types on custom schemes (e.g., Wails issue [v2, linux] custom AssetsHandler ignores HTML video's src on production #1568) suggest this layer can be problematic.
Overriding/Ignoring of Headers by WebKitGTK for Custom Schemes:
It's possible that even if Wails correctly calls the C APIs to set the headers, WebKitGTK might ignore, override, or not fully expose these headers to the web engine's loader when the response is for a custom wails:// scheme, particularly for binary content that initiates a specific loader path (like the WASM compiler). The "No response headers" in devtools is a strong indicator that the headers set via C API are not making it to the inspection layer.
Less Likely: contentTypeSniffer Interference:
The contentTypeSniffer wraps the webview.ResponseWriter. It only attempts to http.DetectContentType and set it if no Content-Type is already present on the underlying writer's Header() map. If httputil.ReverseProxy correctly populates this map from Vite's response, the sniffer should not interfere. The issue appears to be downstream from this, in the actual delivery to WebKitGTK.
The text was updated successfully, but these errors were encountered:
Uh oh!
There was an error while loading. Please reload this page.
Description
Affected Wails Version: v2.10 (and likely other v2 versions)
Frontend Setup: Vite (v5) with TypeScript, Rust/WASM via
wasm-pack --target web
.Setup:
Note: Most of the text of this issue is written by Gemini 2.5 Pro with the context of my debugging attempts for the last 2 days + all the code of assetserver of wails' master branch.
Problem Description:
In
wails dev
mode, whenfrontend:dev:serverUrl
is configured to point to a Vite development server, WebAssembly (.wasm
) files fetched bywasm-bindgen
's JavaScript glue are ultimately served to the WebKit webview via thewails://
protocol without the necessaryContent-Type: application/wasm
header. This occurs even if Vite serves the.wasm
file with the correctContent-Type
to Wails'sExternalAssetHandler
proxy.The absence of the correct
Content-Type
header on the response received by the webview causesWebAssembly.instantiateStreaming
to fail. Whilewasm-bindgen
's glue code may fall back toWebAssembly.instantiate(ArrayBuffer)
, this often results in an incompletely initialized WASM instance where standard WebAssembly JavaScript APIs, particularly access toWebAssembly.Memory
(and thuswasm_bindgen::memory()
from Rust), are non-functional.Observed Flow in
wails dev
:* The Wails webview requests the initial
index.html
and subsequentlysrc/lib/wasm.ts
andsrc/wasm-generated/pkg/app.js
. Wails'sAssetHandler
proxies these requests to Vite's HTTP dev server. The content is served back to the webview, but theimport.meta.url
context within these loaded scripts becomeswails://wails.localhost:34115/src/...
.* The
app.js
(glue) attempts to fetchapp_bg.wasm
using a URL resolved towails://wails.localhost:34115/src/wasm-generated/pkg/app_bg.wasm
.* Wails's
AssetHandler
intercepts thiswails://
request forapp_bg.wasm
.* Its
ExternalAssetHandler
component then successfully fetcheshttp://localhost:34115/src/wasm-generated/pkg/app_bg.wasm
from Vite. Vite serves this withContent-Type: application/wasm
to Wails's proxy.* Wails's
AssetHandler
then serves the received.wasm
binary content back to the webview in response to thewails://.../app_bg.wasm
request.* Crucially, inspecting this final response to the webview (e.g., via WebKit Network DevTools) shows "No response headers" or that the
Content-Type
header from Vite's response was not propagated.* The
wasm-bindgen
JS glue logs a warning: "WebAssembly.instantiateStreaming
failed because your server does not serve Wasm withapplication/wasm
MIME type."* Subsequent attempts to use
wasm_bindgen::memory()
from within Rust fail, indicating theWebAssembly.Memory
object was not correctly linked or initialized.To Reproduce
Setup:
* Wails v2 project with Vite frontend (for Svelte/TS)
* Rust/WASM module built with
wasm-pack --target web --out-dir frontend/src/some-dir/pkg
.* Vite configured with
vite-plugin-wasm
,vite-plugin-top-level-await
, andoptimizeDeps.exclude
for the WASM package.* Wails
wails.json
hasfrontend:dev:serverUrl
pointing to Vite's HTTP dev server (e.g.,http://localhost:34115
).* Frontend JavaScript (e.g., in
src/lib/wasm.ts
) statically imports thewasm-bindgen
JS glue (e.g.,import initApp from '../wasm-generated/pkg/app.js';
).*
initApp()
is called, which then (internally, vianew URL('./app_bg.wasm', import.meta.url)
) attempts to fetch the companion.wasm
file.Expected behaviour
Wails's
ExternalAssetHandler
, when proxying a response from the Vite dev server (which includes aContent-Type: application/wasm
header for.wasm
files), should preserve or correctly set thisContent-Type
header on the response it ultimately sends to the webview, even when serving via thewails://
scheme. This would allowWebAssembly.instantiateStreaming
to succeed and ensure full WASM API functionality.Screenshots
Attempted Fixes
The location of the bug hasn't been pinpointed exactly so for any other wails devs who want to use WASM, here is the workaround I am considering: inlining WASM binary
or using AssetServer.Middleware.I briefly got inlined WASM to work with functional WASM browser APIs so this one is confirmed to work but I originally ruled against it because it looked too brittle.
1. Manual WASM Inlining (JS Glue Modification)
.wasm
binary is Base64 encoded.wasm-bindgen
-generated JavaScript glue file (e.g.,log_engine.js
) is modified by a build script (e.g., a Node.js or shell script).base64ToArrayBuffer
helper function within the JS glue.wasm-bindgen
's primary initialization function (typically the default export,async function __wbg_init(module_or_path)
) to bypass its internalfetch
logic and instead use the embeddedArrayBuffer
(e.g., by settingmodule_or_path = WASM_BINARY_BUFFER;
before__wbg_load
is called)..wasm
file, thereby avoiding thewails://
Content-Type issue for the binary itself.wasm-bindgen
's internal state (particularlywasm.memory
whichwasm_bindgen::memory()
relies on) is correctly initialized after instantiating from the buffer, this method has been shown to result in functional WebAssembly browser APIs.wasm-bindgen
's generated JS glue is non-trivial. The glue code is auto-generated and its internal structure can change betweenwasm-bindgen
versions, making such patches fragile and hard to maintain.WebAssembly.instantiate
as anArrayBuffer
without relying onwails://
for fetching the binary itself with correct headers, the core WASM instantiation and API linkage can work. The difficulty lies in achieving this without breakingwasm-bindgen
's own setup logic.2.
WailsAssetServer.Middleware
(Theoretical, Untested for this Specific WASM Case)Revised Assessment → Likely Ineffective for API Access Issue): Since the middleware operates on the Go http.ResponseWriter before this final translation to the webview for wails:// requests, if the Wails-to-webview interface or the webview itself is the point of failure for header recognition for custom schemes, the middleware alone won't fix the WASM API access issue. Therefore, this middleware approach is now considered unlikely to be a complete solution for enabling full WASM API functionality in the current wails dev environment.
System Details
Additional context
Possible Root Causes for Missing
Content-Type
onwails://
Response:The issue where the
Content-Type: application/wasm
header (received from the Vite dev server by Wails'sExternalAssetHandler
) is not present on the final response to the WebKitGTK webview forwails://
scheme requests appears to stem from the interaction between Wails's Go code and the underlying WebKitGTK/libsoup APIs for custom scheme handling.Issue in Wails's CGO Bridging or WebKitGTK/libsoup API Usage for Custom Schemes (Linux):
ExternalAssetHandler
useshttputil.ReverseProxy
, which should preserve headers from the upstream Vite server (includingContent-Type: application/wasm
) onto the Gohttp.ResponseWriter
it's given.ResponseWriter
is a Wails wrapper (webview.ResponseWriter
) which, on Linux, is implemented inv2/pkg/assetserver/webview/responsewriter_linux.go
.WriteHeader
method inresponsewriter_linux.go
callswebkit_uri_scheme_request_finish
(defined inv2/pkg/assetserver/webview/webkit2_36+.go
).webkit_uri_scheme_request_finish
function explicitly attempts to set theContent-Type
and all other HTTP headers on theWebKitURISchemeResponse
using CGO calls to WebKitGTK/libsoup functions:C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
C.soup_message_headers_append(hdrs, cName, cValue)
followed byC.webkit_uri_scheme_response_set_http_headers(resp, hdrs)
..wasm
file served viawails://
. This points to a potential issue in:webkit_uri_scheme_response_set_content_type
,webkit_uri_scheme_response_set_http_headers
,soup_message_headers_append
) are being used by Wails for custom scheme responses.Content-Type
for binary types likeapplication/wasm
) for requests made over custom URL schemes (likewails://
). Historical Wails issues with other media types on custom schemes (e.g., Wails issue [v2, linux] custom AssetsHandler ignores HTML video's src on production #1568) suggest this layer can be problematic.Overriding/Ignoring of Headers by WebKitGTK for Custom Schemes:
wails://
scheme, particularly for binary content that initiates a specific loader path (like the WASM compiler). The "No response headers" in devtools is a strong indicator that the headers set via C API are not making it to the inspection layer.Less Likely:
contentTypeSniffer
Interference:contentTypeSniffer
wraps thewebview.ResponseWriter
. It only attempts tohttp.DetectContentType
and set it if noContent-Type
is already present on the underlying writer'sHeader()
map. Ifhttputil.ReverseProxy
correctly populates this map from Vite's response, the sniffer should not interfere. The issue appears to be downstream from this, in the actual delivery to WebKitGTK.The text was updated successfully, but these errors were encountered: