-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[V3] Refactor binding transport layer #4702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v3-alpha
Are you sure you want to change the base?
Conversation
WalkthroughThis PR introduces a pluggable IPC transport architecture (Transport interfaces and HTTPTransport), a WebSocket transport example (backend + frontend), refactors MessageProcessor to a request-driven API (RuntimeRequest / Args), adds an errs package with codegen, and updates the runtime/runtime bindings to support custom transports via setTransport/getTransport. Changes
Sequence Diagram(s)sequenceDiagram
participant FE as Frontend (bindings)
participant RT as Runtime (setTransport)
participant CT as Custom Transport (e.g., WebSocket)
participant Srv as Server Transport (HTTP/WebSocket)
participant MP as MessageProcessor
Note over FE,MP: New flow using custom transport
FE->>RT: Call(object, method, args)
RT->>CT: transport.call(object, method, windowName, args)
CT->>Srv: transmit request (WS/other)
Srv->>MP: HandleRuntimeCallWithIDs(ctx, RuntimeRequest)
MP-->>Srv: (result, error)
Srv->>CT: send response
CT-->>RT: resolve promise with result
RT-->>FE: deliver result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas needing extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1)
20-20: Remove unuseddialogResponsesMap.The
dialogResponsesMap is declared, checked ingenerateID, and cleaned up in thedialogfunction'sfinallyblock, but is never populated. This makes all Map operations dead code:
- Line 136:
dialogResponses.has(result)always returns false- Line 151:
dialogResponses.delete(id)is always a no-opGiven the transport layer refactoring described in the PR, this appears to be incomplete cleanup from removing the per-dialog resolver storage pattern.
Apply this diff to remove the unused Map and related operations:
import {newRuntimeCaller, objectNames} from "./runtime.js"; import { nanoid } from './nanoid.js'; // setup window._wails = window._wails || {}; -type PromiseResolvers = Omit<PromiseWithResolvers<any>, "promise">; - const call = newRuntimeCaller(objectNames.Dialog); -const dialogResponses = new Map<string, PromiseResolvers>();function generateID(): string { - let result; - do { - result = nanoid(); - } while (dialogResponses.has(result)); - return result; + return nanoid(); }function dialog(type: number, options: MessageDialogOptions | OpenFileDialogOptions | SaveFileDialogOptions = {}): Promise<any> { const id = generateID(); - return call(type, Object.assign({ "dialog-id": id }, options)).finally(() => { - dialogResponses.delete(id) - }); + return call(type, Object.assign({ "dialog-id": id }, options)); }Also applies to: 136-136, 147-153
v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1)
95-119: Cancellation no longer fires becauserunningis never true
runningstaysfalse, soresult.oncancelledalways takes therequest.then(cancel)path and never sends the immediate cancel request. The cancel only goes out after the call has already resolved, making cancellation ineffective. Fliprunningto true when the transport call starts and reset it once the promise settles.- let running = false; + let running = true; @@ - request.then((res) => { - callResponses.delete(id); - result.resolve(res) - }, (err) => { - callResponses.delete(id); - result.reject(err); - }); + request.then((res) => { + running = false; + callResponses.delete(id); + result.resolve(res); + }, (err) => { + running = false; + callResponses.delete(id); + result.reject(err); + });
🧹 Nitpick comments (3)
v3/internal/runtime/runtime.go (1)
10-20: Consider logging JSON marshal errors.The function silently ignores
json.Marshalerrors on line 13-16, which may make debugging difficult if flags fail to serialize. Consider logging the error to help diagnose configuration issues while still allowing initialization to proceed.Apply this diff to add error logging:
func Core(flags map[string]any) string { flagsStr := "" if len(flags) > 0 { f, err := json.Marshal(flags) - if err == nil { + if err != nil { + // Log error but continue - don't block runtime initialization + fmt.Fprintf(os.Stderr, "Warning: failed to marshal flags: %v\n", err) + } else { flagsStr += fmt.Sprintf("window._wails.flags=%s;", f) } } return runtimeInit + flagsStr + invoke + environment }Note: You'll need to import
"os"as well.v3/examples/websocket-transport/assets/index.html (1)
334-346: Consider optimizing connection status polling.The connection status is polled every second with
setInterval. For a production application, consider:
- Using WebSocket connection/disconnection events for immediate updates
- Reducing polling frequency to reduce CPU usage
For a demo/example, the current implementation is acceptable.
v3/examples/websocket-transport/GreetService.go (1)
42-50: Guard greetCount against concurrent calls
Service methods can be invoked concurrently when multiple frontend requests arrive, sogreetCount++will race and emit inconsistent counts. Please switch toatomic.Int64(or protect it with a mutex) before emitting events.-import "context" -import "fmt" -import "time" +import ( + "context" + "fmt" + "sync/atomic" + "time" +) type GreetService struct { - greetCount int + greetCount atomic.Int64 app *application.App } func (g *GreetService) Greet(name string) string { - g.greetCount++ - result := fmt.Sprintf("Hello, %s! (Greeted %d times via WebSocket)", name, g.greetCount) + count := g.greetCount.Add(1) + result := fmt.Sprintf("Hello, %s! (Greeted %d times via WebSocket)", name, count) if g.app != nil { - g.app.Event.Emit("greet:count", g.greetCount) + g.app.Event.Emit("greet:count", count) }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
v3/examples/dev/go.sumis excluded by!**/*.sumv3/examples/file-association/go.sumis excluded by!**/*.sumv3/examples/gin-example/go.sumis excluded by!**/*.sumv3/examples/gin-routing/go.sumis excluded by!**/*.sumv3/examples/gin-service/go.sumis excluded by!**/*.sumv3/examples/notifications/go.sumis excluded by!**/*.sumv3/go.sumis excluded by!**/*.sumv3/tests/window-visibility-test/go.sumis excluded by!**/*.sum
📒 Files selected for processing (58)
v3/examples/dev/go.mod(1 hunks)v3/examples/file-association/go.mod(1 hunks)v3/examples/gin-example/go.mod(1 hunks)v3/examples/gin-routing/go.mod(1 hunks)v3/examples/gin-service/go.mod(1 hunks)v3/examples/notifications/go.mod(1 hunks)v3/examples/websocket-transport/GreetService.go(1 hunks)v3/examples/websocket-transport/README.md(1 hunks)v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js(1 hunks)v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js(1 hunks)v3/examples/websocket-transport/assets/index.html(1 hunks)v3/examples/websocket-transport/assets/websocket-transport.js(1 hunks)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js(1 hunks)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js(1 hunks)v3/examples/websocket-transport/main.go(1 hunks)v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/go.mod(1 hunks)v3/internal/assetserver/bundledassets/runtime.js(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts(3 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts(2 hunks)v3/internal/runtime/runtime.go(1 hunks)v3/internal/runtime/runtime_darwin.go(0 hunks)v3/internal/runtime/runtime_linux.go(0 hunks)v3/internal/runtime/runtime_windows.go(0 hunks)v3/pkg/application/CUSTOM_TRANSPORT.md(1 hunks)v3/pkg/application/application.go(2 hunks)v3/pkg/application/application_options.go(1 hunks)v3/pkg/application/event_manager.go(0 hunks)v3/pkg/application/messageprocessor.go(4 hunks)v3/pkg/application/messageprocessor_application.go(2 hunks)v3/pkg/application/messageprocessor_args.go(1 hunks)v3/pkg/application/messageprocessor_browser.go(1 hunks)v3/pkg/application/messageprocessor_call.go(4 hunks)v3/pkg/application/messageprocessor_clipboard.go(2 hunks)v3/pkg/application/messageprocessor_contextmenu.go(2 hunks)v3/pkg/application/messageprocessor_dialog.go(4 hunks)v3/pkg/application/messageprocessor_events.go(2 hunks)v3/pkg/application/messageprocessor_params.go(0 hunks)v3/pkg/application/messageprocessor_screens.go(2 hunks)v3/pkg/application/messageprocessor_system.go(1 hunks)v3/pkg/application/messageprocessor_window.go(4 hunks)v3/pkg/application/transport.go(1 hunks)v3/pkg/application/transport_event_ipc.go(1 hunks)v3/pkg/application/transport_http.go(1 hunks)v3/pkg/application/webview_window.go(0 hunks)v3/pkg/application/webview_window_darwin.go(5 hunks)v3/pkg/application/webview_window_linux.go(1 hunks)v3/pkg/application/webview_window_windows.go(1 hunks)v3/pkg/application/window.go(1 hunks)v3/pkg/errs/README.md(1 hunks)v3/pkg/errs/codegen/error_functions/main.go(1 hunks)v3/pkg/errs/error_functions.gen.go(1 hunks)v3/pkg/errs/errors.go(1 hunks)v3/pkg/errs/utils.go(1 hunks)v3/tests/window-visibility-test/go.mod(1 hunks)
💤 Files with no reviewable changes (6)
- v3/pkg/application/event_manager.go
- v3/internal/runtime/runtime_darwin.go
- v3/pkg/application/webview_window.go
- v3/internal/runtime/runtime_linux.go
- v3/internal/runtime/runtime_windows.go
- v3/pkg/application/messageprocessor_params.go
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-15T22:33:30.639Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:30.639Z
Learning: In the Wails framework's TypeScript bindings, the import path "/wails/runtime.js" is intentionally absolute and should not be changed to a relative path.
Applied to files:
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.jsv3/internal/runtime/desktop/@wailsio/runtime/src/system.tsv3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.jsv3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.jsv3/internal/runtime/desktop/@wailsio/runtime/src/index.tsv3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts
📚 Learning: 2025-01-15T22:33:47.244Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:47.244Z
Learning: In the Wails framework, files with the header comment "Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL" are automatically generated and should not be modified manually.
Applied to files:
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.jsv3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.
Applied to files:
v3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_events.gov3/pkg/application/messageprocessor_window.gov3/pkg/application/messageprocessor_screens.gov3/pkg/errs/errors.gov3/pkg/application/messageprocessor_clipboard.gov3/pkg/application/messageprocessor_application.gov3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.
Applied to files:
v3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_events.gov3/pkg/application/messageprocessor_window.gov3/pkg/application/messageprocessor_screens.gov3/pkg/errs/errors.gov3/pkg/application/messageprocessor_clipboard.gov3/pkg/application/messageprocessor_application.gov3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.
Applied to files:
v3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_window.gov3/pkg/application/messageprocessor.go
📚 Learning: 2025-10-17T23:16:11.570Z
Learnt from: Sammy-T
Repo: wailsapp/wails PR: 4570
File: v2/internal/frontend/desktop/linux/window_webkit6.go:97-108
Timestamp: 2025-10-17T23:16:11.570Z
Learning: For webkit_6/GTK4 builds in v2/internal/frontend/desktop/linux/window_webkit6.go, GTK widget creation should not be wrapped in invokeOnMainThread. The activation mechanism (activateWg + onActivate export) already handles thread safety, and additional wrapping would cause issues.
Applied to files:
v3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_windows.gov3/pkg/application/webview_window_darwin.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_windows.gov3/pkg/application/webview_window_darwin.gov3/internal/assetserver/bundledassets/runtime.js
📚 Learning: 2024-09-20T23:34:29.841Z
Learnt from: nixpare
Repo: wailsapp/wails PR: 3763
File: v3/examples/keybindings/main.go:16-17
Timestamp: 2024-09-20T23:34:29.841Z
Learning: In the codebase, `application.Options.KeyBindings` uses the `application.Window` type, whereas `application.WebviewWindowOptions.KeyBindings` uses `*application.WebviewWindow`. This is intentional and acceptable.
Applied to files:
v3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_windows.gov3/pkg/application/webview_window_darwin.go
📚 Learning: 2025-02-25T17:13:05.652Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4100
File: v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts:222-228
Timestamp: 2025-02-25T17:13:05.652Z
Learning: The user has chosen to maintain the function name `Error` in the dialogs module despite it shadowing the global Error constructor. This is a deliberate choice due to documentation generator compatibility concerns, and the risk is mitigated by using `window.Error` when referencing the global constructor and by the strictly type-checked modular nature of the code.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts
📚 Learning: 2025-02-13T01:08:11.993Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/internal/runtime/desktop/@wailsio/runtime/src/calls.js:69-71
Timestamp: 2025-02-13T01:08:11.993Z
Learning: In JavaScript, Promise.resolve() schedules its then/catch callbacks as microtasks that execute asynchronously, so a try/catch block around Promise.resolve() will properly catch any errors that occur in those callbacks.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/examples/websocket-transport/main.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/pkg/application/application.gov3/examples/websocket-transport/GreetService.go
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.
Applied to files:
v3/pkg/application/messageprocessor_contextmenu.go
📚 Learning: 2025-04-18T05:57:34.711Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.711Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.
Applied to files:
v3/examples/websocket-transport/GreetService.go
🧬 Code graph analysis (28)
v3/pkg/application/messageprocessor_dialog.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidDialogCallErrorf(174-181)WrapInvalidDialogCallErrorf(183-194)v3/pkg/application/dialogs.go (3)
MessageDialogOptions(72-79)OpenFileDialogOptions(169-187)SaveFileDialogOptions(362-376)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Add(20-22)Echo(29-31)GetTime(37-39)Greet(46-48)
v3/pkg/application/webview_window_linux.go (1)
v3/internal/runtime/runtime.go (1)
Core(10-20)
v3/pkg/application/messageprocessor_system.go (4)
v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (3)
Environment(87-89)Capabilities(54-56)IsDarkMode(45-47)v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)
Flags(38-38)v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidSystemCallErrorf(114-121)
v3/pkg/application/application_options.go (1)
v3/pkg/application/transport.go (1)
Transport(18-26)
v3/pkg/application/transport.go (1)
v3/pkg/application/messageprocessor.go (1)
MessageProcessor(65-70)
v3/pkg/application/messageprocessor_events.go (5)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/events.go (1)
CustomEvent(52-58)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidEventsCallErrorf(333-344)NewInvalidEventsCallErrorf(324-331)
v3/pkg/application/messageprocessor_call.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (4)
NewInvalidBindingCallErrorf(264-271)WrapInvalidBindingCallErrorf(273-284)NewBindingCallFailedErrorf(294-301)WrapBindingCallFailedErrorf(303-314)v3/pkg/application/bindings.go (6)
CallOptions(17-21)BoundMethod(68-79)CallError(31-35)ReferenceError(26-26)TypeError(27-27)RuntimeError(28-28)
v3/pkg/application/webview_window_windows.go (1)
v3/internal/runtime/runtime.go (1)
Core(10-20)
v3/pkg/application/messageprocessor_browser.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidBrowserCallErrorf(84-91)WrapInvalidBrowserCallErrorf(93-104)v3/pkg/application/urlvalidator.go (1)
ValidateAndSanitizeURL(11-49)
v3/pkg/application/transport_event_ipc.go (2)
v3/pkg/application/application.go (1)
App(306-397)v3/pkg/application/events.go (1)
CustomEvent(52-58)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidRuntimeCallErrorf(363-374)NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/bindings.go (1)
CallError(31-35)
v3/pkg/application/messageprocessor_window.go (5)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidWindowCallErrorf(24-31)WrapInvalidWindowCallErrorf(33-44)v3/pkg/application/webview_window_options.go (1)
RGBA(145-147)
v3/pkg/application/messageprocessor_screens.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/screenmanager.go (1)
Screen(25-38)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidScreensCallErrorf(153-164)NewInvalidScreensCallErrorf(144-151)
v3/examples/websocket-transport/main.go (4)
v3/examples/websocket-transport/transport_websocket.go (1)
NewWebSocketTransport(52-70)v3/pkg/application/application.go (1)
New(48-195)v3/pkg/application/application_options.go (2)
Options(12-117)MacOptions(187-193)v3/pkg/application/transport.go (1)
Transport(18-26)
v3/pkg/application/application.go (5)
v3/pkg/application/transport.go (3)
Transport(18-26)TransportHTTPHandler(65-67)AssetServerTransport(40-54)v3/pkg/application/transport_http.go (2)
NewHTTPTransport(20-31)HTTPTransportWithLogger(37-41)v3/pkg/application/events.go (1)
WailsEventListener(83-85)v3/pkg/application/transport_event_ipc.go (1)
EventIPCTransport(3-5)v3/pkg/application/application_options.go (1)
Options(12-117)
v3/pkg/errs/errors.go (1)
v3/pkg/errs/utils.go (1)
Cause(21-37)
v3/pkg/application/messageprocessor_contextmenu.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidContextMenuCallErrorf(213-224)NewInvalidContextMenuCallErrorf(204-211)
v3/pkg/application/messageprocessor_clipboard.go (3)
v3/pkg/application/messageprocessor.go (1)
RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidClipboardCallErrorf(243-254)NewInvalidClipboardCallErrorf(234-241)
v3/examples/websocket-transport/assets/websocket-transport.js (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
nanoid(16-16)clientId(32-32)v3/internal/assetserver/bundledassets/runtime.debug.js (7)
id(69-69)id(208-208)id(2460-2460)i(70-70)i(1066-1066)i(1414-1414)callId(160-160)
v3/pkg/application/messageprocessor.go (3)
v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/window.go (1)
Window(9-104)
v3/pkg/application/messageprocessor_application.go (2)
v3/pkg/application/messageprocessor.go (1)
RuntimeRequest(44-63)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidApplicationCallErrorf(54-61)
v3/pkg/application/webview_window_darwin.go (1)
v3/internal/runtime/runtime.go (1)
Core(10-20)
v3/examples/websocket-transport/transport_websocket.go (2)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/events.go (1)
CustomEvent(52-58)
v3/pkg/errs/utils.go (1)
v3/pkg/errs/errors.go (2)
ErrorType(5-5)WailsError(7-12)
v3/examples/websocket-transport/GreetService.go (4)
v3/pkg/application/application.go (2)
App(306-397)Get(44-46)v3/pkg/application/services.go (2)
ServiceStartup(98-100)ServiceOptions(17-40)v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Greet(46-48)GetTime(37-39)Echo(29-31)Add(20-22)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Greet(46-48)GetTime(37-39)Echo(29-31)Add(20-22)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (4)
RuntimeTransport(59-59)setTransport(57-57)getTransport(58-58)clientId(61-61)v3/internal/assetserver/bundledassets/runtime.debug.js (5)
method(1155-1155)url(110-110)body(111-114)headers(118-121)response(125-129)
v3/pkg/errs/error_functions.gen.go (2)
v3/pkg/errs/errors.go (13)
ErrorType(5-5)InvalidWindowCallError(15-15)InvalidApplicationCallError(16-16)InvalidBrowserCallError(17-17)InvalidSystemCallError(18-18)InvalidScreensCallError(19-19)InvalidDialogCallError(20-20)InvalidContextMenuCallError(21-21)InvalidClipboardCallError(22-22)InvalidBindingCallError(23-23)BindingCallFailedError(24-24)InvalidEventsCallError(25-25)InvalidRuntimeCallError(26-26)v3/pkg/errs/utils.go (3)
Cause(21-37)Is(9-19)Has(39-57)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js
[error] 1-1: This array contains an empty slots..
The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined
(lint/suspicious/noSparseArray)
[error] 1-1: Do not add then to a class.
(lint/suspicious/noThenProperty)
[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.
'i' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
🪛 markdownlint-cli2 (0.18.1)
v3/examples/websocket-transport/README.md
15-15: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
v3/pkg/application/CUSTOM_TRANSPORT.md
15-15: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
🔇 Additional comments (27)
v3/examples/gin-service/go.mod (1)
60-60: Dependency bump is reasonable.The go-webview2 v1.0.21 → v1.0.22 bump is a patch version increment that aligns with coordinated updates across the codebase and the PR's transport layer refactoring goals.
v3/examples/file-association/go.mod (1)
39-39: Dependency bump is consistent with coordinated updates.Part of the systematic go-webview2 v1.0.22 update across example modules.
v3/examples/dev/go.mod (1)
39-39: Dependency bump is consistent with coordinated updates.Part of the systematic go-webview2 v1.0.22 update across example modules.
v3/go.mod (2)
38-38: Dependency bump is consistent across the codebase.The go-webview2 v1.0.21 → v1.0.22 bump in the main module aligns with updates across all example and test modules.
20-20: WebSocket dependency addition uses current, secure version.The gorilla/websocket v1.5.3 dependency is the latest stable release. A CVE-2020-27813 vulnerability in frame length handling was fixed in v1.4.1, so v1.5.3 includes this security patch. No newer security advisories exist for this version. The dependency addition appropriately supports the custom WebSocket transport implementation.
v3/examples/notifications/go.mod (1)
42-42: Dependency bump is consistent with coordinated updates.Part of the systematic go-webview2 v1.0.22 update across example modules.
v3/examples/gin-example/go.mod (1)
58-58: Dependency bump is consistent with coordinated updates.Part of the systematic go-webview2 v1.0.22 update across example modules.
v3/tests/window-visibility-test/go.mod (1)
43-43: Dependency bump is consistent with coordinated updates.Part of the systematic go-webview2 v1.0.22 update across test and example modules.
v3/pkg/application/window.go (1)
5-5: LGTM!The import formatting change is clean. The removal of the Callback interface (mentioned in the AI summary) aligns with the PR's goal of refactoring to a request/response pattern.
v3/internal/assetserver/bundledassets/runtime.js (1)
1-1: Generated/bundled code - static analysis warnings expected.This is a minified and bundled JavaScript file. The static analysis warnings (empty slots, redeclare, etc.) are typical for bundled code and can be safely ignored. The source TypeScript files should be reviewed instead if logic verification is needed.
v3/pkg/errs/README.md (1)
1-5: LGTM!Clear and concise documentation for the errs package. The description of the code generation workflow is helpful for maintainers.
v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (1)
54-56: Verify the IPC-based capability fetch after fixing the constant collision.The change from HTTP fetch to IPC call is appropriate for the transport refactoring. However, this will only work correctly after fixing the
SystemCapabilitiesconstant value collision flagged in the previous comment.v3/pkg/application/application_options.go (1)
107-116: LGTM!The new
Transportfield is well-documented with clear usage examples. The documentation properly explains the default behavior and when custom transports might be needed.v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)
1-8: Auto-generated file - no review needed.This file is automatically generated as indicated by the header comment. The re-export pattern is standard for generated bindings.
v3/pkg/application/webview_window_darwin.go (2)
1358-1403: LGTM!The whitespace formatting changes in the
applyLiquidGlassfunction improve readability without altering logic.
1094-1094: Code initialization path is sound—no flag initialization risk exists.The concern about
globalApplication.impl.GetFlags(globalApplication.options)executing before proper initialization is unfounded. The execution order is:
NewApplication()populatesglobalApplicationandglobalApplication.optionsnewPlatformApp()is called (Linux variant immediately accessesparent.options.Nameduring construction, proving options is ready)- Windows are created and hooks are registered
WebViewDidFinishNavigationfires after navigation completesAdditionally,
GetFlags()defensively initializes an emptymap[string]anyifoptions.Flagsis nil, preventing any nil dereference. The same pattern is used consistently across all platforms (Darwin, Linux, Windows).v3/pkg/application/webview_window_linux.go (1)
355-355: Consistent with Darwin implementation.The change to pass flags to
runtime.Core()matches the pattern used in the Darwin implementation. The same verification concern applies: ensureglobalApplication.impl.GetFlags(globalApplication.options)is properly initialized before the WindowLoadChanged event fires.v3/pkg/application/webview_window_windows.go (1)
2140-2140: LGTM! Core signature correctly updated.The change properly adapts to the new
runtime.Core(flags map[string]any)signature, passing application-specific flags fromGetFlagsfor injection into the webview. This aligns with the PR objective to inject all application-specified flags.v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)
55-62: LGTM! Transport API exports added.The new export block cleanly exposes the transport-related APIs (
setTransport,getTransport,RuntimeTransport, etc.) to support custom transports. The comment clearly documents the purpose of these exports.v3/examples/websocket-transport/README.md (1)
1-113: LGTM! Clear and comprehensive documentation.The README provides excellent documentation for the WebSocket transport example, with clear explanations of architecture, setup, and features. The ASCII diagram and code examples enhance understanding.
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)
1-8: Generated file - no review needed.This file is automatically generated (as indicated by the header comments). Generated bindings should not be manually modified.
v3/pkg/application/transport_event_ipc.go (1)
7-18: LGTM! Thread-safe event dispatching with proper cancellation handling.The implementation correctly:
- Uses RLock for concurrent-safe read access to windows
- Checks for event cancellation during iteration
- Properly releases the lock in both early-return and normal-completion paths
- Dispatches events to all windows efficiently
v3/examples/websocket-transport/main.go (1)
13-58: LGTM! Clear example of custom transport usage.The example demonstrates the WebSocket transport feature effectively:
- Simple transport instantiation with
NewWebSocketTransport- Clear configuration with application options
- Helpful comments explaining automatic event forwarding
- Consistent port usage (9099) across the example
v3/examples/websocket-transport/assets/index.html (1)
237-357: LGTM! Comprehensive demo with proper error handling.The JavaScript implementation demonstrates the WebSocket transport integration well:
- Proper module imports with cache busting
- Clean integration with generated bindings
- Event subscriptions for real-time updates
- Comprehensive error handling
- Clear user feedback
v3/pkg/application/messageprocessor_contextmenu.go (1)
31-45: Context menu handler refactor looks solidThe migration to
RuntimeRequestplus the standardized invalid-context-menu error propagation is clean and keeps the control flow tight. Nicely done.v3/pkg/application/messageprocessor_screens.go (1)
19-33: Screen method routing follows the new pattern wellReturning data/errors directly and wrapping failures with
errskeeps this aligned with the rest of the processor refactor. Looks good.v3/examples/gin-routing/go.mod (1)
58-58: Standard patch-level dependency update confirmed safe and compatible.Verification confirms
go-webview2 v1.0.22is stable (released August 12, 2025) with no security vulnerabilities. The patch version bump (v1.0.21 → v1.0.22) includes a feature addition ("Add source information in message callbacks"), which remains backward compatible and consistent with the PR-wide dependency updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
🧹 Nitpick comments (7)
v3/pkg/application/transport_event_ipc.go (1)
9-17: Consider deferring the unlock for robustness.The manual
RUnlockpaths work today, but adeferimmediately after theRLockwould make this future-proof against new returns/panics inside the loop.You could restructure like:
t.app.windowsLock.RLock() defer t.app.windowsLock.RUnlock() for _, window := range t.app.windows { if event.IsCancelled() { return } window.DispatchWailsEvent(event) }v3/internal/runtime/runtime.go (1)
10-19: Core flag injection logic is sound, consider logging marshal errors.The implementation correctly marshals the flags map to JSON and injects it into the runtime initialization. However, JSON marshal errors are silently ignored (line 14), which could hide issues with invalid flag values at runtime.
Consider adding debug logging for marshal failures to aid troubleshooting:
func Core(flags map[string]any) string { flagsStr := "" if len(flags) > 0 { f, err := json.Marshal(flags) - if err == nil { + if err != nil { + // Consider: log.Printf("Failed to marshal flags: %v", err) or use slog + } else { flagsStr += fmt.Sprintf("window._wails.flags=%s;", f) } } return runtimeInit + flagsStr + invoke + environment }v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
12-12: Consider removing unused import from the generation template.The
$Createimport is unused in this generated file. If the code generator template always includes this import, consider updating the template to only import what's needed for each specific binding file.v3/examples/websocket-transport/assets/websocket-transport.js (1)
31-42: Consider adding a limit to the message queue.The
messageQueuehas no size limit. If the WebSocket connection fails for an extended period, the queue could grow unbounded and cause memory issues.Consider adding a maximum queue size:
constructor(url, options = {}) { this.url = url; this.ws = null; this.wsReady = false; this.pendingRequests = new Map(); this.messageQueue = []; this.reconnectTimer = null; this.reconnectDelay = options.reconnectDelay || 2000; this.requestTimeout = options.requestTimeout || 30000; + this.maxQueueSize = options.maxQueueSize || 100; this.connect(); }Then enforce the limit when queueing:
} else { + if (this.messageQueue.length >= this.maxQueueSize) { + reject(new Error('Message queue full')); + return; + } this.messageQueue.push(message); this.connect().catch(reject); }v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
12-12: Consider removing unused import from the generation template.Same as the frontend version: the
$Createimport is unused. This should be addressed in the code generation template to avoid including unused imports.v3/pkg/application/CUSTOM_TRANSPORT.md (1)
16-31: Add a language identifier to the code fenceLine 16 uses a fenced block without a language tag, which trips markdownlint (MD040). Mark it as
text(or another appropriate identifier) so the docs build stays clean.-``` +```text ┌─────────────────────────────────────────────────┐ │ Frontend (TypeScript) │ │ - Generated bindings still work │ @@ └─────────────────────────────────────────────────┘ -``` +```v3/pkg/errs/error_functions.gen.go (1)
13-13: Consider addingUnwrap()for standard library compatibility.The
wailsErrortype implementsCause()but notUnwrap() error, which is the standard library interface for error chaining. This meanserrors.Is()anderrors.As()won't automatically walk the error chain, and third-party code expectingUnwrap()won't work. Your customIs/Has/Causeutilities compensate, but addingUnwrap()as an alias would improve interoperability:func (w *wailsError) Unwrap() error { return w.cause }This would make the error chain traversable by both custom and standard library functions.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
v3/examples/dev/go.sumis excluded by!**/*.sumv3/examples/file-association/go.sumis excluded by!**/*.sumv3/examples/gin-example/go.sumis excluded by!**/*.sumv3/examples/gin-routing/go.sumis excluded by!**/*.sumv3/examples/gin-service/go.sumis excluded by!**/*.sumv3/examples/notifications/go.sumis excluded by!**/*.sumv3/go.sumis excluded by!**/*.sumv3/tests/window-visibility-test/go.sumis excluded by!**/*.sum
📒 Files selected for processing (58)
v3/examples/dev/go.mod(1 hunks)v3/examples/file-association/go.mod(1 hunks)v3/examples/gin-example/go.mod(1 hunks)v3/examples/gin-routing/go.mod(1 hunks)v3/examples/gin-service/go.mod(1 hunks)v3/examples/notifications/go.mod(1 hunks)v3/examples/websocket-transport/GreetService.go(1 hunks)v3/examples/websocket-transport/README.md(1 hunks)v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js(1 hunks)v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js(1 hunks)v3/examples/websocket-transport/assets/index.html(1 hunks)v3/examples/websocket-transport/assets/websocket-transport.js(1 hunks)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js(1 hunks)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js(1 hunks)v3/examples/websocket-transport/main.go(1 hunks)v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/go.mod(1 hunks)v3/internal/assetserver/bundledassets/runtime.js(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts(3 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts(2 hunks)v3/internal/runtime/runtime.go(1 hunks)v3/internal/runtime/runtime_darwin.go(0 hunks)v3/internal/runtime/runtime_linux.go(0 hunks)v3/internal/runtime/runtime_windows.go(0 hunks)v3/pkg/application/CUSTOM_TRANSPORT.md(1 hunks)v3/pkg/application/application.go(2 hunks)v3/pkg/application/application_options.go(1 hunks)v3/pkg/application/event_manager.go(0 hunks)v3/pkg/application/messageprocessor.go(4 hunks)v3/pkg/application/messageprocessor_application.go(2 hunks)v3/pkg/application/messageprocessor_args.go(1 hunks)v3/pkg/application/messageprocessor_browser.go(1 hunks)v3/pkg/application/messageprocessor_call.go(4 hunks)v3/pkg/application/messageprocessor_clipboard.go(2 hunks)v3/pkg/application/messageprocessor_contextmenu.go(2 hunks)v3/pkg/application/messageprocessor_dialog.go(4 hunks)v3/pkg/application/messageprocessor_events.go(2 hunks)v3/pkg/application/messageprocessor_params.go(0 hunks)v3/pkg/application/messageprocessor_screens.go(2 hunks)v3/pkg/application/messageprocessor_system.go(1 hunks)v3/pkg/application/messageprocessor_window.go(4 hunks)v3/pkg/application/transport.go(1 hunks)v3/pkg/application/transport_event_ipc.go(1 hunks)v3/pkg/application/transport_http.go(1 hunks)v3/pkg/application/webview_window.go(0 hunks)v3/pkg/application/webview_window_darwin.go(5 hunks)v3/pkg/application/webview_window_linux.go(1 hunks)v3/pkg/application/webview_window_windows.go(1 hunks)v3/pkg/application/window.go(1 hunks)v3/pkg/errs/README.md(1 hunks)v3/pkg/errs/codegen/error_functions/main.go(1 hunks)v3/pkg/errs/error_functions.gen.go(1 hunks)v3/pkg/errs/errors.go(1 hunks)v3/pkg/errs/utils.go(1 hunks)v3/tests/window-visibility-test/go.mod(1 hunks)
💤 Files with no reviewable changes (6)
- v3/pkg/application/event_manager.go
- v3/pkg/application/webview_window.go
- v3/internal/runtime/runtime_darwin.go
- v3/pkg/application/messageprocessor_params.go
- v3/internal/runtime/runtime_windows.go
- v3/internal/runtime/runtime_linux.go
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-15T22:33:30.639Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:30.639Z
Learning: In the Wails framework's TypeScript bindings, the import path "/wails/runtime.js" is intentionally absolute and should not be changed to a relative path.
Applied to files:
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.jsv3/internal/runtime/desktop/@wailsio/runtime/src/runtime.tsv3/internal/runtime/desktop/@wailsio/runtime/src/system.tsv3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.jsv3/internal/runtime/desktop/@wailsio/runtime/src/index.tsv3/internal/assetserver/bundledassets/runtime.js
📚 Learning: 2025-01-15T22:33:47.244Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:47.244Z
Learning: In the Wails framework, files with the header comment "Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL" are automatically generated and should not be modified manually.
Applied to files:
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.jsv3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.
Applied to files:
v3/pkg/application/messageprocessor_screens.gov3/pkg/application/messageprocessor_application.gov3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_window.gov3/pkg/application/messageprocessor_events.gov3/pkg/errs/codegen/error_functions/main.gov3/pkg/application/messageprocessor_clipboard.gov3/pkg/errs/errors.gov3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.
Applied to files:
v3/pkg/application/messageprocessor_screens.gov3/pkg/application/messageprocessor_application.gov3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_window.gov3/pkg/application/messageprocessor_events.gov3/pkg/application/messageprocessor_clipboard.gov3/pkg/errs/errors.gov3/pkg/errs/error_functions.gen.go
📚 Learning: 2025-02-13T01:08:11.993Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/internal/runtime/desktop/@wailsio/runtime/src/calls.js:69-71
Timestamp: 2025-02-13T01:08:11.993Z
Learning: In JavaScript, Promise.resolve() schedules its then/catch callbacks as microtasks that execute asynchronously, so a try/catch block around Promise.resolve() will properly catch any errors that occur in those callbacks.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.
Applied to files:
v3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_window.gov3/pkg/application/messageprocessor.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/pkg/application/messageprocessor_window.gov3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_darwin.gov3/pkg/application/webview_window_windows.gov3/internal/assetserver/bundledassets/runtime.js
📚 Learning: 2025-01-24T22:41:18.566Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4031
File: v3/pkg/application/menu.go:199-202
Timestamp: 2025-01-24T22:41:18.566Z
Learning: In the Wails menu system (v3/pkg/application/menu.go), shared state between menus is intentionally designed and desirable. Methods like `Append()` and `Prepend()` should maintain shared references to menu items rather than creating deep copies.
Applied to files:
v3/pkg/application/messageprocessor_contextmenu.go
📚 Learning: 2025-02-25T17:13:05.652Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4100
File: v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts:222-228
Timestamp: 2025-02-25T17:13:05.652Z
Learning: The user has chosen to maintain the function name `Error` in the dialogs module despite it shadowing the global Error constructor. This is a deliberate choice due to documentation generator compatibility concerns, and the risk is mitigated by using `window.Error` when referencing the global constructor and by the strictly type-checked modular nature of the code.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts
📚 Learning: 2025-04-18T05:57:34.711Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.711Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.
Applied to files:
v3/examples/websocket-transport/GreetService.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/examples/websocket-transport/GreetService.gov3/examples/websocket-transport/main.go
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/examples/websocket-transport/main.go
📚 Learning: 2025-10-17T23:16:11.570Z
Learnt from: Sammy-T
Repo: wailsapp/wails PR: 4570
File: v2/internal/frontend/desktop/linux/window_webkit6.go:97-108
Timestamp: 2025-10-17T23:16:11.570Z
Learning: For webkit_6/GTK4 builds in v2/internal/frontend/desktop/linux/window_webkit6.go, GTK widget creation should not be wrapped in invokeOnMainThread. The activation mechanism (activateWg + onActivate export) already handles thread safety, and additional wrapping would cause issues.
Applied to files:
v3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_darwin.gov3/pkg/application/webview_window_windows.go
📚 Learning: 2024-09-20T23:34:29.841Z
Learnt from: nixpare
Repo: wailsapp/wails PR: 3763
File: v3/examples/keybindings/main.go:16-17
Timestamp: 2024-09-20T23:34:29.841Z
Learning: In the codebase, `application.Options.KeyBindings` uses the `application.Window` type, whereas `application.WebviewWindowOptions.KeyBindings` uses `*application.WebviewWindow`. This is intentional and acceptable.
Applied to files:
v3/pkg/application/webview_window_linux.gov3/pkg/application/webview_window_darwin.go
🧬 Code graph analysis (29)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Add(20-22)Echo(29-31)GetTime(37-39)Greet(46-48)
v3/pkg/application/messageprocessor_screens.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/screenmanager.go (1)
Screen(25-38)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidScreensCallErrorf(153-164)NewInvalidScreensCallErrorf(144-151)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (4)
RuntimeTransport(59-59)setTransport(57-57)getTransport(58-58)clientId(61-61)v3/internal/assetserver/bundledassets/runtime.debug.js (5)
method(1155-1155)url(110-110)body(111-114)headers(118-121)response(125-129)
v3/pkg/application/messageprocessor_application.go (2)
v3/pkg/application/messageprocessor.go (1)
RuntimeRequest(44-63)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidApplicationCallErrorf(54-61)
v3/pkg/application/transport.go (1)
v3/pkg/application/messageprocessor.go (1)
MessageProcessor(65-70)
v3/pkg/application/messageprocessor_dialog.go (5)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidDialogCallErrorf(174-181)WrapInvalidDialogCallErrorf(183-194)v3/pkg/application/dialogs.go (3)
MessageDialogOptions(72-79)OpenFileDialogOptions(169-187)SaveFileDialogOptions(362-376)
v3/pkg/application/application_options.go (1)
v3/pkg/application/transport.go (1)
Transport(18-26)
v3/pkg/application/messageprocessor_window.go (5)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidWindowCallErrorf(24-31)WrapInvalidWindowCallErrorf(33-44)v3/pkg/application/webview_window_options.go (1)
RGBA(145-147)
v3/pkg/application/messageprocessor_events.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/events.go (1)
CustomEvent(52-58)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidEventsCallErrorf(333-344)NewInvalidEventsCallErrorf(324-331)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Add(20-22)Echo(29-31)GetTime(37-39)Greet(46-48)
v3/examples/websocket-transport/assets/websocket-transport.js (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
nanoid(16-16)clientId(32-32)v3/internal/assetserver/bundledassets/runtime.debug.js (7)
id(69-69)id(208-208)id(2460-2460)i(70-70)i(1066-1066)i(1414-1414)callId(160-160)
v3/pkg/application/messageprocessor_call.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (4)
NewInvalidBindingCallErrorf(264-271)WrapInvalidBindingCallErrorf(273-284)NewBindingCallFailedErrorf(294-301)WrapBindingCallFailedErrorf(303-314)v3/pkg/application/bindings.go (6)
CallOptions(17-21)BoundMethod(68-79)CallError(31-35)ReferenceError(26-26)TypeError(27-27)RuntimeError(28-28)
v3/examples/websocket-transport/transport_websocket.go (2)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/events.go (1)
CustomEvent(52-58)
v3/pkg/application/transport_event_ipc.go (2)
v3/pkg/application/application.go (1)
App(306-397)v3/pkg/application/events.go (1)
CustomEvent(52-58)
v3/pkg/application/messageprocessor_contextmenu.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidContextMenuCallErrorf(213-224)NewInvalidContextMenuCallErrorf(204-211)
v3/pkg/application/messageprocessor_clipboard.go (3)
v3/pkg/application/messageprocessor.go (1)
RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidClipboardCallErrorf(243-254)NewInvalidClipboardCallErrorf(234-241)
v3/pkg/application/messageprocessor_browser.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidBrowserCallErrorf(84-91)WrapInvalidBrowserCallErrorf(93-104)v3/pkg/application/urlvalidator.go (1)
ValidateAndSanitizeURL(11-49)
v3/pkg/application/messageprocessor_system.go (4)
v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (3)
Environment(87-89)Capabilities(54-56)IsDarkMode(45-47)v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)
Flags(38-38)v3/pkg/application/messageprocessor.go (1)
RuntimeRequest(44-63)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidSystemCallErrorf(114-121)
v3/examples/websocket-transport/GreetService.go (4)
v3/pkg/application/application.go (2)
App(306-397)Get(44-46)v3/pkg/application/services.go (2)
ServiceStartup(98-100)ServiceOptions(17-40)v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Greet(46-48)GetTime(37-39)Echo(29-31)Add(20-22)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Greet(46-48)GetTime(37-39)Echo(29-31)Add(20-22)
v3/examples/websocket-transport/main.go (4)
v3/examples/websocket-transport/transport_websocket.go (1)
NewWebSocketTransport(52-70)v3/pkg/application/application.go (1)
New(48-195)v3/pkg/application/application_options.go (2)
Options(12-117)BundledAssetFileServer(168-170)v3/pkg/application/transport.go (1)
Transport(18-26)
v3/pkg/application/webview_window_linux.go (1)
v3/internal/runtime/runtime.go (1)
Core(10-20)
v3/pkg/errs/utils.go (1)
v3/pkg/errs/errors.go (2)
ErrorType(5-5)WailsError(7-12)
v3/pkg/errs/errors.go (1)
v3/pkg/errs/utils.go (1)
Cause(21-37)
v3/pkg/application/application.go (10)
v3/pkg/application/transport.go (3)
Transport(18-26)TransportHTTPHandler(65-67)AssetServerTransport(40-54)v3/pkg/application/transport_http.go (2)
NewHTTPTransport(20-31)HTTPTransportWithLogger(37-41)v3/pkg/application/events.go (1)
WailsEventListener(83-85)v3/pkg/application/transport_event_ipc.go (1)
EventIPCTransport(3-5)v3/pkg/application/application_options.go (3)
Middleware(144-144)Options(12-117)ChainMiddleware(147-154)v3/internal/assetserver/middleware.go (2)
Middleware(10-10)ChainMiddleware(13-20)v3/internal/assetserver/common.go (1)
ServeFile(29-40)v3/internal/assetserver/bundledassets/runtime_dev.go (1)
RuntimeJS(8-8)v3/internal/assetserver/bundledassets/runtime_production.go (1)
RuntimeJS(8-8)v3/internal/assetserver/options.go (1)
Options(10-29)
v3/pkg/errs/error_functions.gen.go (2)
v3/pkg/errs/errors.go (13)
ErrorType(5-5)InvalidWindowCallError(15-15)InvalidApplicationCallError(16-16)InvalidBrowserCallError(17-17)InvalidSystemCallError(18-18)InvalidScreensCallError(19-19)InvalidDialogCallError(20-20)InvalidContextMenuCallError(21-21)InvalidClipboardCallError(22-22)InvalidBindingCallError(23-23)BindingCallFailedError(24-24)InvalidEventsCallError(25-25)InvalidRuntimeCallError(26-26)v3/pkg/errs/utils.go (3)
Cause(21-37)Is(9-19)Has(39-57)
v3/pkg/application/webview_window_darwin.go (1)
v3/internal/runtime/runtime.go (1)
Core(10-20)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidRuntimeCallErrorf(363-374)NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/bindings.go (1)
CallError(31-35)
v3/pkg/application/webview_window_windows.go (1)
v3/internal/runtime/runtime.go (1)
Core(10-20)
v3/pkg/application/messageprocessor.go (2)
v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidRuntimeCallErrorf(354-361)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js
[error] 1-1: This array contains an empty slots..
The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined
(lint/suspicious/noSparseArray)
[error] 1-1: Do not add then to a class.
(lint/suspicious/noThenProperty)
[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.
'i' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
🪛 markdownlint-cli2 (0.18.1)
v3/examples/websocket-transport/README.md
15-15: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
v3/pkg/application/CUSTOM_TRANSPORT.md
16-16: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (32)
v3/examples/gin-example/go.mod (1)
57-57: LGTM: Consistent indirect dependency updates across examples.The indirect dependency updates (go-webview2 v1.0.21→v1.0.22 and removal of pkg/errors) are consistently applied across all example and test modules. These are automatic results of dependency resolution and align with changes in the main v3 module.
Note: This approval applies to identical changes in v3/examples/dev/go.mod, v3/examples/file-association/go.mod, v3/examples/gin-routing/go.mod, v3/examples/notifications/go.mod, and v3/tests/window-visibility-test/go.mod.
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (1)
55-62: Confirm public API surface for transport utilities.The new exports successfully expose the transport abstraction layer, enabling custom transport implementations as outlined in the PR objectives. The
RuntimeTransporttype andsetTransport/getTransportfunctions provide a clean, typed API for transport customization.Consider whether
objectNamesandclientIdshould be part of the public API. These identifiers appear to be internal runtime details. If they're intended for advanced custom transport implementations, ensure they're documented. If they're purely internal, consider keeping them unexported to reduce public API surface and avoid unintended dependencies.Can you verify the intended use case for exposing these identifiers?
v3/go.mod (1)
20-20: No changes required—gorilla/websocket v1.5.3 is current and secure.Verification confirms v1.5.3 is the latest stable release (June 2024). The single security advisory on file only affects versions before 1.4.1; v1.5.3 is unaffected.
v3/examples/gin-service/go.mod (1)
59-59: Dependency bump matches transport updates.No issues spotted with moving to
go-webview2 v1.0.22; the examples stay aligned with the core module.v3/pkg/application/window.go (1)
9-105: Window surface cleanup looks good.Removing the legacy
Callbackembedding matches the new transport design and keeps the public surface tighter.v3/pkg/errs/README.md (1)
1-5: Helpful README addition.Clear instructions on extending the errs package—looks good.
v3/pkg/application/webview_window_darwin.go (1)
1094-1094: LGTM!The updated call to
runtime.Corenow correctly passes application flags viaglobalApplication.impl.GetFlags(globalApplication.options), aligning with the new signature and the PR's goal of injecting app-specified flags into the webview at initialization.v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)
1-8: Auto-generated binding file looks correct.This is a standard auto-generated binding index that re-exports the GreetService module. No review needed per the file header comment.
v3/pkg/application/application_options.go (1)
107-116: LGTM!The new
Transportfield is a well-documented public API addition that enables pluggable IPC transport layers. The comprehensive documentation clearly explains the default behavior and use cases, making this a clean extension point for custom transports like WebSocket.v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts (1)
54-56: Good: Capabilities now uses IPC instead of HTTP.The migration from
fetch("/wails/capabilities")to IPC-basedcall(SystemCapabilities)aligns with the PR's goal of decoupling from HTTP transport. Once the duplicate method ID is fixed, this will enable capabilities to work with any transport implementation.v3/pkg/application/webview_window_linux.go (1)
354-356: LGTM!The updated
runtime.Corecall now correctly passes application flags, consistent with the Darwin and Windows implementations. This ensures flags are properly injected across all platforms.v3/pkg/application/messageprocessor_application.go (1)
19-45: LGTM! Clean refactor to request-driven architecture.The migration from HTTP-centric to RuntimeRequest-based handling is well executed. The function now returns values instead of side-effecting via HTTP responses, enabling reuse across different transport layers (HTTP, WebSocket, etc.).
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js (1)
1-8: Auto-generated bindings file.This file is automatically generated (as indicated by the header comment) and follows the expected pattern for re-exporting service modules in Wails bindings.
v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts (1)
147-153: Excellent simplification of dialog handling.The removal of custom promise plumbing in favor of directly returning the call() result is cleaner and more maintainable. The finally block ensures proper cleanup regardless of success or failure, which is the idiomatic approach.
v3/pkg/application/webview_window_windows.go (1)
2140-2140: Flag injection properly integrated.The change enables application-specified flags to be passed to the frontend runtime. This aligns with the PR's goal to inject all app flags (not just resize handle dimensions) into the webview.
v3/examples/websocket-transport/assets/index.html (1)
237-356: Well-structured WebSocket transport example.The example demonstrates the pluggable transport architecture effectively:
- Proper initialization with error handling
- Event subscription using the new transport
- Generated bindings work seamlessly with custom transport
- Clear UI feedback for connection status
The hardcoded WebSocket URL (
ws://localhost:9099/wails/ws) is appropriate for an example/demo application.v3/pkg/errs/utils.go (2)
9-19: Clean error type checking implementation.The
Isfunction properly useserrors.Asto check if an error implementsWailsErrorand compares the error type. The nil check prevents panics.
21-37: Correct cause unwrapping logic.The
Causefunction follows the standard pattern for unwrapping errors that implement aCause()method. It properly handles nil causes and missing interfaces.v3/pkg/application/messageprocessor_contextmenu.go (1)
31-45: Consistent refactor to request-driven architecture.The changes align with the broader pattern of migrating message processors to use
RuntimeRequestand return(any, error). Error handling with theerrspackage provides consistent error types across the transport layer.v3/pkg/application/messageprocessor_screens.go (1)
19-34: Well-executed migration to request-driven pattern.The refactor successfully moves from HTTP-centric to functional return values. Error propagation from
Window.GetScreen()is properly wrapped with context, maintaining error chain integrity.v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
1-48: LGTM! Auto-generated binding file follows standard pattern.The generated binding file correctly implements the GreetService methods using the
$Call.ByIDpattern. All functions properly delegate to the Wails runtime with their respective method IDs.v3/pkg/application/transport.go (2)
8-26: LGTM! Clean interface design.The
Transportinterface is well-designed with clear lifecycle methods and comprehensive documentation explaining its purpose and responsibilities.
28-54: LGTM! Well-designed optional interface.The
AssetServerTransportinterface properly embedsTransportand adds asset-serving capability. The documentation clearly explains when and how this interface should be implemented.v3/pkg/errs/codegen/error_functions/main.go (2)
11-67: LGTM! Template correctly generates error handling functions.The template generates appropriate constructor, wrapper, and checker functions for each error type with proper error chaining support.
77-86: No type filtering needed—all constants inerrors.goare alreadyErrorType.Verification confirms that the const block contains only
ErrorTypeconstants (12 declarations, each explicitly typed). The current AST inspection correctly collects only ErrorType names without needing defensive type filtering. The suggested diff adds unnecessary complexity and should be disregarded.Likely an incorrect or invalid review comment.
v3/examples/websocket-transport/assets/websocket-transport.js (3)
108-174: LGTM! Message handling logic is well-implemented.The
handleMessagemethod properly handles both response and event message types, with appropriate error handling and integration with the Wails runtime.
180-223: LGTM! Runtime call implementation follows the correct pattern.The
callmethod correctly implements the RuntimeTransport interface with proper timeout handling, request tracking, and message construction.
17-25: Fix array index out of bounds in nanoid implementation.The alphabet has 60 characters, but
Math.random() * 64can generate indices 0-63, causing array access beyond bounds when the index is 60-63. This results inundefinedbeing added to the ID string.Apply this diff:
function nanoid(size = 21) { const alphabet = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'; let id = ''; let i = size; while (i--) { - id += alphabet[(Math.random() * 64) | 0]; + id += alphabet[(Math.random() * alphabet.length) | 0]; } return id; }Likely an incorrect or invalid review comment.
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
1-48: LGTM! Duplicate auto-generated binding for assets directory.This file is identical to the frontend binding version and serves the asset-serving context. The duplication is expected for auto-generated bindings.
v3/internal/assetserver/bundledassets/runtime.js (1)
1-1: Static analysis warnings are false positives for minified code.The Biome linter flags sparse arrays, variable redeclarations, and use-before-declaration issues, but these are inherent to minified/bundled JavaScript and do not indicate actual problems. The
thenproperty on the CancellablePromise class is correct (it implements the Promise interface). Since this is a generated bundle, manual line-by-line review is impractical; focus should be on integration testing of the runtime API.v3/pkg/errs/error_functions.gen.go (2)
7-22: LGTM! Error wrapper implementation is correct.The
wailsErrorstruct correctly implements the custom error interface withCause(),Error(),Msg(), andErrorType()methods. Error formatting is clear and includes the error chain when a cause is present.
24-382: LGTM! Error constructor patterns are consistent across all types.All 12 error types follow the same pattern:
New*Errorfcreates errors without a causeWrap*Errorfwraps existing errors with nil-safetyIs*Errorchecks immediate error typeHas*Errorchecks the error chainThe implementation is correct and the consistency aids maintainability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (5)
v3/pkg/application/CUSTOM_TRANSPORT.md (1)
16-31: Language hint added - previous issue resolved.The architecture diagram now correctly uses the
textlanguage identifier, addressing the markdownlint MD040 warning from the previous review.v3/pkg/application/messageprocessor_clipboard.go (1)
24-27: Validation error correctly surfaced - previous issue resolved.The code now correctly uses
errs.NewInvalidClipboardCallErrorfinstead of wrapping a nil error, ensuring the validation failure is properly returned to the caller.v3/pkg/application/transport_http.go (3)
73-130: Error handling improved - previous issue resolved.All error paths in
handleRuntimeRequestnow correctly return after callinghttpError, preventing fall-through and potential nil dereferences.
142-160: Set headers before calling WriteHeader.Lines 143-144 call
WriteHeaderbefore setting theContent-Typeheader. This causes the same issue as intext(): the header is set after the response status is written, making it ineffective.Apply this diff:
func (t *HTTPTransport) json(rw http.ResponseWriter, data any) { - rw.WriteHeader(http.StatusOK) rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) // convert data to json var jsonPayload = []byte("{}") var err error if data != nil { jsonPayload, err = json.Marshal(data) if err != nil { t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err) return } } _, err = rw.Write(jsonPayload) if err != nil { t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) return } }
132-140: Set headers before calling WriteHeader.Lines 133-134 call
WriteHeaderbefore setting theContent-Typeheader. OnceWriteHeaderis called, the header map is frozen and subsequentHeader().Set()calls have no effect. The client won't receive theContent-Typeheader.Apply this diff:
func (t *HTTPTransport) text(rw http.ResponseWriter, data string) { - rw.WriteHeader(http.StatusOK) rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(http.StatusOK) _, err := rw.Write([]byte(data)) if err != nil { t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) return } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
v3/tests/window-visibility-test/go.sumis excluded by!**/*.sum
📒 Files selected for processing (11)
v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts(2 hunks)v3/pkg/application/CUSTOM_TRANSPORT.md(1 hunks)v3/pkg/application/application.go(2 hunks)v3/pkg/application/messageprocessor_args.go(1 hunks)v3/pkg/application/messageprocessor_clipboard.go(2 hunks)v3/pkg/application/messageprocessor_dialog.go(4 hunks)v3/pkg/application/transport_http.go(1 hunks)v3/pkg/errs/codegen/error_functions/main.go(1 hunks)v3/pkg/errs/errors.go(1 hunks)v3/pkg/errs/utils.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts
- v3/pkg/errs/utils.go
- v3/pkg/application/messageprocessor_args.go
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.
Applied to files:
v3/pkg/errs/errors.gov3/pkg/application/messageprocessor_dialog.gov3/pkg/errs/codegen/error_functions/main.gov3/pkg/application/messageprocessor_clipboard.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.
Applied to files:
v3/pkg/errs/errors.gov3/pkg/application/messageprocessor_dialog.gov3/pkg/application/messageprocessor_clipboard.go
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/internal/commands/appimage_testfiles/main.go:295-299
Timestamp: 2024-10-08T22:11:37.054Z
Learning: In `v3/internal/commands/appimage_testfiles/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-04-18T05:57:34.711Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4128
File: v3/examples/gin-service/services/gin_service.go:67-85
Timestamp: 2025-04-18T05:57:34.711Z
Learning: In Wails services (like GinService), initializing the app field in ServiceStartup rather than in the constructor is an acceptable pattern, as ServiceStartup is guaranteed to be called before any HTTP requests are handled.
Applied to files:
v3/pkg/application/application.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/pkg/application/application.go
🧬 Code graph analysis (6)
v3/pkg/errs/errors.go (1)
v3/pkg/errs/utils.go (1)
Cause(20-40)
v3/pkg/application/messageprocessor_dialog.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
NewInvalidDialogCallErrorf(174-181)WrapInvalidDialogCallErrorf(183-194)v3/pkg/application/dialogs.go (3)
MessageDialogOptions(72-79)OpenFileDialogOptions(169-187)SaveFileDialogOptions(362-376)
v3/pkg/application/application.go (5)
v3/pkg/application/transport.go (3)
Transport(18-26)TransportHTTPHandler(65-67)AssetServerTransport(40-54)v3/pkg/application/transport_http.go (2)
NewHTTPTransport(20-31)HTTPTransportWithLogger(37-41)v3/pkg/application/events.go (1)
WailsEventListener(83-85)v3/pkg/application/transport_event_ipc.go (1)
EventIPCTransport(3-5)v3/internal/assetserver/common.go (1)
ServeFile(29-40)
v3/pkg/application/messageprocessor_clipboard.go (3)
v3/pkg/application/messageprocessor.go (1)
RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (1)
NewInvalidClipboardCallErrorf(234-241)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidRuntimeCallErrorf(363-374)NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/bindings.go (1)
CallError(31-35)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/examples/websocket-transport/assets/websocket-transport.js (1)
WebSocketTransport(30-248)v3/pkg/application/events.go (1)
CustomEvent(52-58)
🪛 LanguageTool
v3/pkg/application/CUSTOM_TRANSPORT.md
[grammar] ~37-~37: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...plement the Transport Interface Create a custom transport by implementing the Transport interfa...
(A_UNCOUNTABLE)
[formatting] ~84-~84: These punctuation marks differ from each other. Use only one if you are ending a sentence.
Context: ...ace that will be used to handle requests.: ```typescript const { setTransport } =...
(DOUBLE_PUNCTUATION_PREMIUM)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: semgrep-cloud-platform/scan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
v3/pkg/application/transport.go (1)
59-62: Clarify TransportHTTPHandler middleware descriptionThe new sentence is hard to parse (“use Handler() in asset server middlewares…”). Please rewrite it as clear, complete sentences so it’s obvious that Wails calls
Handler()afterStart()to wrap the asset server handler forwails://requests.-// When a transport implements this interface, Wails will use Handler() in -// asset server middlewares that may provide handling for request done from webview to wails:// URLs. +// When a transport implements this interface, Wails will call Handler() after Start() +// to obtain middleware that wraps the asset server handler. Use it to intercept +// requests coming from the webview (wails:// URLs) before they reach the asset server.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
v3/examples/websocket-transport/GreetService.go(1 hunks)v3/examples/websocket-transport/README.md(1 hunks)v3/examples/websocket-transport/assets/websocket-transport.js(1 hunks)v3/examples/websocket-transport/main.go(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts(3 hunks)v3/pkg/application/messageprocessor_call.go(4 hunks)v3/pkg/application/transport.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- v3/examples/websocket-transport/main.go
- v3/examples/websocket-transport/GreetService.go
- v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-01-15T22:33:30.639Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4001
File: v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts:0-0
Timestamp: 2025-01-15T22:33:30.639Z
Learning: In the Wails framework's TypeScript bindings, the import path "/wails/runtime.js" is intentionally absolute and should not be changed to a relative path.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts
🧬 Code graph analysis (4)
v3/pkg/application/messageprocessor_call.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (4)
NewInvalidBindingCallErrorf(264-271)WrapInvalidBindingCallErrorf(273-284)NewBindingCallFailedErrorf(294-301)WrapBindingCallFailedErrorf(303-314)v3/pkg/application/bindings.go (3)
CallOptions(17-21)BoundMethod(68-79)CallError(31-35)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts (4)
RuntimeTransport(59-59)setTransport(57-57)getTransport(58-58)clientId(61-61)v3/internal/assetserver/bundledassets/runtime.debug.js (5)
method(1155-1155)url(110-110)body(111-114)headers(118-121)response(125-129)
v3/pkg/application/transport.go (1)
v3/pkg/application/messageprocessor.go (1)
MessageProcessor(65-70)
v3/examples/websocket-transport/assets/websocket-transport.js (2)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
nanoid(16-16)clientId(32-32)v3/internal/assetserver/bundledassets/runtime.debug.js (7)
id(69-69)id(208-208)id(2460-2460)i(70-70)i(1066-1066)i(1414-1414)callId(160-160)
🪛 LanguageTool
v3/examples/websocket-transport/README.md
[grammar] ~3-~3: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...e This example demonstrates how to use a custom transport like WebSocket for Wails IPC instead of...
(A_UNCOUNTABLE)
[uncategorized] ~46-~46: The preposition ‘for’ seems more likely in this position.
Context: ... the UI - WebSocket server listening on ws://localhost:9099/wails/ws - Rea...
(AI_HYDRA_LEO_REPLACE_ON_FOR)
🔇 Additional comments (2)
v3/pkg/application/messageprocessor_call.go (1)
118-130: Good catch on propagating non-CallError failuresThanks for wrapping unexpected errors coming back from
boundMethod.Call; this keeps runtime callers from getting silentnullresults when something actually failed.v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (1)
101-129: Thanks for preserving falsy argsGreat change on the default transport: keeping
argswhen they’re0,false, or""avoids the regression we worried about earlier, and the custom transport hook mirrors the new POST workflow nicely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (4)
v3/examples/websocket-transport/transport_websocket.go (2)
118-133: Stop() must not clear the clients map before deferred cleanups complete.When
Stop()replacesw.clientswith a new map (line 129), any deferred cleanup inhandleWebSocket(lines 150-156) that subsequently tries toclose(w.clients[conn])will findniland panic with "close of nil channel."The past review comment on lines 150-156 suggested capturing
messageChanat the top ofhandleWebSocketand closing the captured variable in the defer, but that change was not applied here.Apply this fix in
Stop():func (w *WebSocketTransport) Stop() error { if w.server == nil { return nil } - // Close all client connections w.mu.Lock() for conn := range w.clients { conn.Close() } - w.clients = make(map[*websocket.Conn]chan *WebSocketMessage) w.mu.Unlock() return w.server.Shutdown(context.Background()) }And update the defer in
handleWebSocket(see next comment).
150-157: Capture and close the local messageChan, not the map lookup.Line 153 closes
w.clients[conn], which evaluates tonilifStop()has already removed the entry from the map, causing a panic. The past review explicitly recommended capturingmessageChanin a local variable immediately after line 144 and closing that captured value in the defer.Apply this diff:
w.mu.Lock() messageChan := make(chan *WebSocketMessage, 100) w.clients[conn] = messageChan w.mu.Unlock() ctx, cancel := context.WithCancel(r.Context()) defer func() { w.mu.Lock() - cancel() - close(w.clients[conn]) - delete(w.clients, conn) + if _, ok := w.clients[conn]; ok { + delete(w.clients, conn) + } w.mu.Unlock() + cancel() + close(messageChan) conn.Close() }()v3/pkg/application/transport_http.go (2)
142-160: Headers must be set before WriteHeader is called.Lines 143-144 call
WriteHeaderbeforeHeader().Set, which means the Content-Type header will not be sent. Headers must be set beforeWriteHeaderis called.Apply this diff to fix the header ordering:
func (t *HTTPTransport) json(rw http.ResponseWriter, data any) { - rw.WriteHeader(http.StatusOK) rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) // convert data to json var jsonPayload = []byte("{}") var err error if data != nil { jsonPayload, err = json.Marshal(data) if err != nil { t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err) return } } _, err = rw.Write(jsonPayload) if err != nil { t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) return } }
132-140: Headers must be set before WriteHeader is called.Lines 133-134 call
WriteHeaderbeforeHeader().Set, which means the Content-Type header will not be sent. In Go'snet/http, onceWriteHeaderorWriteis called, headers are flushed and furtherHeader().Setcalls are ignored.Apply this diff to fix the header ordering:
func (t *HTTPTransport) text(rw http.ResponseWriter, data string) { - rw.WriteHeader(http.StatusOK) rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(http.StatusOK) _, err := rw.Write([]byte(data)) if err != nil { - t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) + t.error("Unable to write text payload. Please report this to the Wails team!", "error", err) return } }Note: Also fixed the error message on line 137 which incorrectly referenced "json payload" instead of "text payload".
🧹 Nitpick comments (3)
v3/pkg/application/CUSTOM_TRANSPORT.md (1)
35-37: Minor grammar refinement.Per static analysis, "custom transport" (uncountable) reads more idiomatically than "a custom transport" in this technical context.
-Create a custom transport by implementing the `Transport` interface: +Create custom transport by implementing the `Transport` interface:v3/examples/websocket-transport/transport_websocket.go (1)
237-251: Consider non-blocking sends for event broadcasting in production.The current implementation holds
RLockduring the broadcast loop (lines 245-250). If any client's channel is full, the send on line 249 blocks, stalling all concurrent operations that need the lock. For production use, consider a non-blocking send with a select-default or a timeout to drop events for slow clients rather than blocking all others.Example pattern for non-blocking send:
for _, channel := range w.clients { select { case channel <- msg: // Sent successfully default: // Channel full, drop event or log log.Printf("[WebSocket] Dropped event for slow client") } }v3/pkg/application/transport_http.go (1)
73-130: LGTM with minor suggestions.The request handling logic is correct, with proper error handling and early returns. The validation and processing flow is clean.
Two minor consistency suggestions:
Line 108: Consider defining a constant for
"x-wails-client-id"to match the pattern used forwebViewRequestHeaderWindowIdandwebViewRequestHeaderWindowName(lines 97, 107).Lines 98-114: The windowId undergoes string → int → uint32 conversion. While
strconv.Atoireturns an error for invalid input, a negative integer would become a large uint32 after the cast on line 114, which may not be the intended behavior. If window IDs are always non-negative, consider usingstrconv.ParseUintdirectly to match the target type.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/pkg/application/CUSTOM_TRANSPORT.md(1 hunks)v3/pkg/application/transport_http.go(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/pkg/application/transport_http.go
📚 Learning: 2025-08-08T13:15:20.339Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.339Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.
Applied to files:
v3/pkg/application/transport_http.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/examples/websocket-transport/transport_websocket.go
🧬 Code graph analysis (2)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidRuntimeCallErrorf(363-374)NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/bindings.go (1)
CallError(31-35)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/events.go (1)
CustomEvent(52-58)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)
🪛 LanguageTool
v3/pkg/application/CUSTOM_TRANSPORT.md
[grammar] ~37-~37: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...plement the Transport Interface Create a custom transport by implementing the Transport interfa...
(A_UNCOUNTABLE)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
🔇 Additional comments (10)
v3/examples/websocket-transport/transport_websocket.go (5)
56-59: CheckOrigin security posture is acceptable for an example.The blanket
return trueallows any origin to connect. The inline comment correctly warns that production code must validate origins. Given the disclaimer on lines 17-18 that this is an example and not production-ready, this is appropriate.
159-179: Writer goroutine correctly exits on channel close.The
!okcheck on line 164 ensures the goroutine returns immediately whenmessageChanis closed, avoiding the busy-loop that would otherwise consume CPU. The lock is only acquired when a message is available.
181-196: Reader loop correctly handles connection lifecycle.The loop properly detects unexpected close errors (line 186) and spawns concurrent request handlers (line 194) with the per-connection context, allowing multiple in-flight calls without blocking the reader.
199-207: Context is correctly propagated to the runtime handler.Line 204 passes the per-connection
ctxtoHandleRuntimeCallWithIDs, ensuring that long-running binding calls are cancelled when the WebSocket disconnects or the app shuts down.
209-235: Response handling correctly defaults to success and guards against context cancellation.The response defaults to
StatusCode: 200(line 212), so successful calls that returnnilerror are now reported as success. Thectx.Done()check (line 230) prevents sends after the connection context is cancelled, which aligns with the defer inhandleWebSocketthat cancelsctxbefore closingmessageChan.v3/pkg/application/transport_http.go (5)
1-18: LGTM!The package declaration, imports, and struct definition are well-organized and appropriate for an HTTP transport implementation.
20-41: LGTM!The constructor and functional options pattern are implemented correctly. The logger defaults to
slog.Default()and can be customized via the functional option.
43-51: LGTM!The
StartandStopmethods correctly implement the Transport interface. The minimal implementation is appropriate since HTTP transport has no long-lived resources to manage.
53-71: LGTM!The request struct uses pointers to distinguish between missing and zero values, and the Handler middleware correctly routes
/wails/runtimerequests while passing others through.
183-185: LGTM!The error logging helper correctly delegates to the configured logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (2)
v3/pkg/application/transport_http.go (2)
142-160: Headers must be set before calling WriteHeader.Line 143 calls
WriteHeaderbefore line 144 sets theContent-Typeheader. This results in the Content-Type not being set in the response.Apply this diff to fix the header ordering:
func (t *HTTPTransport) json(rw http.ResponseWriter, data any) { - rw.WriteHeader(http.StatusOK) rw.Header().Set("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) // convert data to json var jsonPayload = []byte("{}") var err error if data != nil { jsonPayload, err = json.Marshal(data) if err != nil { t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err) return } } _, err = rw.Write(jsonPayload) if err != nil { t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) return } }
132-140: Headers must be set before calling WriteHeader.Line 133 calls
WriteHeaderbefore line 134 sets theContent-Typeheader. OnceWriteHeaderis called in Go, the response headers are sent and can no longer be modified, so the Content-Type will not be set.Apply this diff to fix the header ordering:
func (t *HTTPTransport) text(rw http.ResponseWriter, data string) { - rw.WriteHeader(http.StatusOK) rw.Header().Set("Content-Type", "text/plain") + rw.WriteHeader(http.StatusOK) _, err := rw.Write([]byte(data)) if err != nil { t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) return } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
v3/examples/websocket-transport/README.md(1 hunks)v3/examples/websocket-transport/assets/websocket-transport.js(1 hunks)v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/pkg/application/CUSTOM_TRANSPORT.md(1 hunks)v3/pkg/application/transport_http.go(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/examples/websocket-transport/transport_websocket.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/pkg/application/transport_http.gov3/examples/websocket-transport/assets/websocket-transport.jsv3/examples/websocket-transport/README.md
📚 Learning: 2025-08-08T13:15:20.339Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.339Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.
Applied to files:
v3/pkg/application/transport_http.go
🧬 Code graph analysis (3)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/examples/websocket-transport/assets/websocket-transport.js (1)
WebSocketTransport(30-230)v3/pkg/application/events.go (1)
CustomEvent(52-58)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidRuntimeCallErrorf(363-374)NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/bindings.go (1)
CallError(31-35)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
nanoid(16-16)clientId(32-32)
🪛 LanguageTool
v3/pkg/application/CUSTOM_TRANSPORT.md
[grammar] ~37-~37: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...plement the Transport Interface Create a custom transport by implementing the Transport interfa...
(A_UNCOUNTABLE)
v3/examples/websocket-transport/README.md
[grammar] ~3-~3: Uncountable nouns are usually not used with an indefinite article. Use simply “custom transport”.
Context: ...e This example demonstrates how to use a custom transport like WebSocket for Wails IPC instead of...
(A_UNCOUNTABLE)
[uncategorized] ~46-~46: The preposition ‘for’ seems more likely in this position.
Context: ... the UI - WebSocket server listening on ws://localhost:9099/wails/ws - Rea...
(AI_HYDRA_LEO_REPLACE_ON_FOR)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (5)
v3/pkg/application/transport_http.go (5)
1-42: Well-structured transport setup with functional options.The package declaration, imports, struct definition, constructor, and functional options follow Go best practices. Previous comment issues have been properly addressed.
43-71: Transport lifecycle and routing logic is correct.The Start/Stop methods are appropriate, the internal request struct design correctly uses pointers to distinguish missing fields from zero values, and the Handler middleware properly routes the runtime endpoint.
73-130: Request handling logic is robust and correct.The handler properly validates input, parses headers, delegates to the message processor, and handles errors appropriately. All error paths correctly return immediately, addressing previous review concerns.
162-184: Error response handling is correctly implemented.This method properly sets Content-Type headers before calling WriteHeader, demonstrating the correct pattern. It appropriately handles both CallError (JSON) and generic errors (plain text).
186-188: Simple and correct error logging helper.The error method appropriately delegates to the logger with variadic arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (1)
v3/pkg/application/transport_http.go (1)
146-154: Consider returning JSONnullfor nil payloads.When
datais nil we currently ship"{}", so a Go binding that returnsnil(or no values) arrives in the frontend as an empty object. The WebSocket transport emitsnull, and consumers often distinguish “no result” from “empty object”. Emittingnullhere keeps the transports consistent and avoids surprising callers.- var jsonPayload = []byte("{}") + var jsonPayload = []byte("null")
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
v3/examples/websocket-transport/assets/websocket-transport.js(1 hunks)v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js(1 hunks)v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/internal/assetserver/bundledassets/runtime.js(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts(1 hunks)v3/pkg/application/messageprocessor_dialog.go(4 hunks)v3/pkg/application/transport_event_ipc.go(1 hunks)v3/pkg/application/transport_http.go(1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-02-25T17:13:05.652Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4100
File: v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts:222-228
Timestamp: 2025-02-25T17:13:05.652Z
Learning: The user has chosen to maintain the function name `Error` in the dialogs module despite it shadowing the global Error constructor. This is a deliberate choice due to documentation generator compatibility concerns, and the risk is mitigated by using `window.Error` when referencing the global constructor and by the strictly type-checked modular nature of the code.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/examples/websocket-transport/assets/websocket-transport.jsv3/internal/runtime/desktop/@wailsio/runtime/src/calls.tsv3/pkg/application/transport_http.go
📚 Learning: 2025-02-13T01:08:11.993Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/internal/runtime/desktop/@wailsio/runtime/src/calls.js:69-71
Timestamp: 2025-02-13T01:08:11.993Z
Learning: In JavaScript, Promise.resolve() schedules its then/catch callbacks as microtasks that execute asynchronously, so a try/catch block around Promise.resolve() will properly catch any errors that occur in those callbacks.
Applied to files:
v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts
📚 Learning: 2024-09-30T06:13:46.595Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/examples/window/main.go:472-475
Timestamp: 2024-09-30T06:13:46.595Z
Learning: In `v3/examples/window/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2024-10-08T22:11:37.054Z
Learnt from: leaanthony
Repo: wailsapp/wails PR: 3763
File: v3/internal/commands/appimage_testfiles/main.go:295-299
Timestamp: 2024-10-08T22:11:37.054Z
Learning: In `v3/internal/commands/appimage_testfiles/main.go`, `time.Sleep` is used within a goroutine and does not block the UI thread.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-01-18T21:19:47.778Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4024
File: v3/pkg/application/services.go:38-51
Timestamp: 2025-01-18T21:19:47.778Z
Learning: In the Wails v3 codebase, panic is used to catch invalid invocations that should never occur in production (programming errors), while error returns are reserved for recoverable error conditions (runtime errors). For example, the `NewService` function in `v3/pkg/application/services.go` uses panic to handle the case where more than one `ServiceOptions` instance is provided, as this is considered an unrecoverable programming error.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-02-04T23:59:43.956Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4045
File: v3/internal/generator/render/info.go:28-68
Timestamp: 2025-02-04T23:59:43.956Z
Learning: In the Wails v3 project, internal functions are designed to panic on nil parameters as they represent contract violations, rather than adding defensive nil checks.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-02-13T01:05:02.267Z
Learnt from: fbbdev
Repo: wailsapp/wails PR: 4066
File: v3/pkg/application/messageprocessor_call.go:174-174
Timestamp: 2025-02-13T01:05:02.267Z
Learning: When handling JSON marshaling errors in Wails v3, the error message from json.Marshal provides sufficient debugging context. Logging raw data is unnecessary and could make logs harder to read.
Applied to files:
v3/pkg/application/messageprocessor_dialog.go
📚 Learning: 2025-08-08T13:15:20.339Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4484
File: v2/internal/frontend/utils/urlValidator.go:25-31
Timestamp: 2025-08-08T13:15:20.339Z
Learning: In Wails v2 (PR wailsapp/wails#4484), for BrowserOpenURL URL validation (v2/internal/frontend/utils/urlValidator.go), maintainers (APshenkin) prefer not to restrict schemes to an http/https allowlist because supported schemes may vary. The allowlist suggestion is declined; continue with the existing denylist approach and generic validation.
Applied to files:
v3/pkg/application/transport_http.go
📚 Learning: 2025-03-24T06:54:22.127Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:0-0
Timestamp: 2025-03-24T06:54:22.127Z
Learning: popaprozac prefers to focus on getting the Notifications API functionality working first and may consider code cleanup/refactoring for payload encoding logic in notifications_windows.go at a later time.
Applied to files:
v3/pkg/application/transport_http.go
📚 Learning: 2025-02-24T06:08:55.645Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4098
File: v3/pkg/services/notifications/notifications_windows.go:91-113
Timestamp: 2025-02-24T06:08:55.645Z
Learning: The JSON quote handling in Windows notifications' activation arguments (v3/pkg/services/notifications/notifications_windows.go) has a known limitation with single-quote collisions that needs to be addressed after initial testing.
Applied to files:
v3/pkg/application/transport_http.go
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/examples/websocket-transport/transport_websocket.go
🧬 Code graph analysis (7)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (4)
Add(20-22)Echo(29-31)GetTime(37-39)Greet(46-48)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
nanoid(16-16)clientId(32-32)
v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts (1)
v3/internal/assetserver/bundledassets/runtime.debug.js (9)
running(2415-2415)request(2414-2414)id(65-65)id(2411-2411)result(525-525)result(2175-2175)result(2317-2317)result(2404-2404)result(2412-2412)
v3/pkg/application/messageprocessor_dialog.go (5)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/window.go (1)
Window(9-104)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/application/dialogs.go (3)
MessageDialogOptions(72-79)OpenFileDialogOptions(169-187)SaveFileDialogOptions(362-376)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidDialogCallErrorf(183-194)NewInvalidDialogCallErrorf(174-181)
v3/pkg/application/transport_event_ipc.go (2)
v3/pkg/application/application.go (1)
App(304-395)v3/pkg/application/events.go (1)
CustomEvent(52-58)
v3/pkg/application/transport_http.go (4)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)v3/pkg/errs/error_functions.gen.go (2)
WrapInvalidRuntimeCallErrorf(363-374)NewInvalidRuntimeCallErrorf(354-361)v3/pkg/application/bindings.go (1)
CallError(31-35)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/events.go (1)
CustomEvent(52-58)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js
[error] 1-1: This array contains an empty slots..
The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined
(lint/suspicious/noSparseArray)
[error] 1-1: Do not add then to a class.
(lint/suspicious/noThenProperty)
[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.
'i' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js (1)
20-47: Bindings align with generated backend IDs.These wrappers match the generated call IDs and keep the cancellable promise contract intact, so the frontend example stays in sync with the Go service.
v3/pkg/application/messageprocessor_dialog.go (1)
62-76: Buffered dialog response channel prevents deadlock.Thanks for buffering the response channel and making the button callbacks non-blocking; this resolves the dialog hang we previously hit.
|
This is an epic PR! I didn't realise you'd take on som many different issues in it 🚀 🎉 Please give me until the end of the weekend to review as it needs a solid look over. It looks like there's a few merge conflicts. If they could be addressed that would be amazing 🙏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
v3/internal/assetserver/bundledassets/runtime.js (1)
1-1: Consider generating bundled runtime at build time.This minified bundle is checked into source control, which can make code reviews challenging and may lead to merge conflicts that are difficult to resolve. While there may be valid reasons for embedding this runtime (simplification, consistency), consider whether it would be better to:
- Keep only the source TypeScript/JavaScript files in the repository
- Generate this bundle during the build process
- Document the build steps clearly for contributors
This approach would make reviews more meaningful (reviewing source changes rather than minified output) and reduce the risk of the bundle getting out of sync with its source.
However, if embedding the pre-built runtime is intentional for the v3-alpha architecture, this can be addressed in a future iteration.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
v3/examples/websocket-transport/assets/index.html(1 hunks)v3/examples/websocket-transport/assets/websocket-transport.js(1 hunks)v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/internal/assetserver/bundledassets/runtime.js(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
📚 Learning: 2025-04-29T23:54:07.488Z
Learnt from: popaprozac
Repo: wailsapp/wails PR: 4256
File: v2/internal/frontend/desktop/linux/notifications.go:27-28
Timestamp: 2025-04-29T23:54:07.488Z
Learning: In Wails v2, unlike v3-alpha which has a `ServiceShutdown` method for services, there is no standardized teardown pattern for frontend implementations. When implementing features that require cleanup (like goroutines or resources), add explicit cleanup methods (e.g., `CleanupNotifications()`) that handle resource release, context cancellation, and connection closure.
Applied to files:
v3/examples/websocket-transport/transport_websocket.go
📚 Learning: 2025-08-08T09:13:16.916Z
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
Applied to files:
v3/examples/websocket-transport/transport_websocket.gov3/examples/websocket-transport/assets/websocket-transport.js
🧬 Code graph analysis (3)
v3/examples/websocket-transport/transport_websocket.go (3)
v3/pkg/application/messageprocessor.go (2)
MessageProcessor(65-70)RuntimeRequest(44-63)v3/pkg/application/events.go (1)
CustomEvent(50-59)v3/pkg/application/messageprocessor_args.go (1)
Args(8-10)
v3/examples/websocket-transport/assets/websocket-transport.js (1)
v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts (2)
nanoid(16-16)clientId(32-32)
v3/internal/assetserver/bundledassets/runtime.js (1)
v3/examples/notifications/frontend/dist/assets/index-Dat4utuQ.js (4)
Be(6-6)fe(1-1)pe(1-1)I(6-6)
🪛 Biome (2.1.2)
v3/internal/assetserver/bundledassets/runtime.js
[error] 1-1: This array contains an empty slots..
The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined
(lint/suspicious/noSparseArray)
[error] 1-1: Do not add then to a class.
(lint/suspicious/noThenProperty)
[error] 1-1: Shouldn't redeclare 'i'. Consider to delete it or rename it.
'i' is defined here:
(lint/suspicious/noRedeclare)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
[error] 1-1: This variable is used before its declaration.
The variable is declared here:
(lint/correctness/noInvalidUseBeforeDeclaration)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (4)
v3/examples/websocket-transport/assets/index.html (1)
237-357: LGTM!The frontend implementation is well-structured with proper error handling, event listener setup, and UI wiring. The cache-busting approach and module imports work correctly for this example scenario.
v3/examples/websocket-transport/assets/websocket-transport.js (1)
30-246: LGTM!The WebSocket transport implementation is solid. All the issues flagged in previous reviews have been properly addressed:
- Connection state guards prevent race conditions
- Message queue is cleared on disconnect
- Falsy response values are handled correctly with
??- Event forwarding integrates cleanly with the Wails runtime
v3/examples/websocket-transport/transport_websocket.go (1)
72-88: LGTM on lifecycle and request handling!The transport lifecycle, connection management, and request processing logic are well-implemented:
- Proper initialization and shutdown sequencing
- Context cancellation properly wired
- Args are safely initialized to prevent nil panics (lines 193-195)
- Response status defaults to 200 for success cases
- Connection context flows through to the runtime handler
Also applies to: 92-115, 133-209, 212-253
v3/internal/assetserver/bundledassets/runtime.js (1)
1-1: No validation issues found—interface is properly documented and exported.The
RuntimeTransportinterface is clearly defined, exported, and documented inv3/internal/runtime/desktop/@wailsio/runtime/src/runtime.tswith JSDoc comments explaining the required.call()method signature. The codebase includes a working example inv3/examples/websocket-transport/showing proper implementation.The runtime implementation checks for null before invoking the transport (
if (customTransport) { return customTransport.call(...) }) and relies on TypeScript's type system for compile-time safety. While the bundled JavaScript loses type information, this is expected and the documented interface pattern provides sufficient guidance for implementers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
docs/src/content/docs/guides/custom-transport.mdx (1)
106-112: Appropriately cautions users but could strengthen security guidance.The notes section responsibly mentions that the WebSocket example may need production hardening. However, consider expanding line 111 with specific guidance on what security aspects developers should address (e.g., authentication, encryption, origin validation).
- You're responsible for error handling, reconnection logic, and security in your custom transport + - You're responsible for error handling, reconnection logic, and security in your custom transport (e.g., authentication, encryption, origin validation, rate limiting)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
docs/src/content/docs/guides/custom-transport.mdx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: APshenkin
Repo: wailsapp/wails PR: 4480
File: v2/internal/frontend/desktop/darwin/message.h:17-19
Timestamp: 2025-08-08T09:13:16.916Z
Learning: In Wails v2 bindings origin verification, processBindingMessage intentionally has different signatures across platforms: Darwin includes an isMainFrame bool (WKWebKit provides it), Linux uses two params (message, source) as WebKitGTK doesn’t expose main-frame info there, and Windows handles origin checks in Go via WebView2 sender/args without a C bridge. This divergence is acceptable/expected per maintainer (APshenkin).
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: Run Go Tests v3 (ubuntu-latest, 1.24)
🔇 Additional comments (2)
docs/src/content/docs/guides/custom-transport.mdx (2)
8-85: Documentation structure and Go examples are clear and accurate.The introduction, architecture diagram, and Go code examples properly reflect the Transport interface and application configuration changes introduced in this PR. The progression from interface definition to application wiring is logical and helpful.
87-104: TypeScript example is well-structured and appropriately addresses the typo fix.The frontend modification example correctly shows usage of the
setTransport()function and the customRuntimeTransportinterface. The TODO comment clearly indicates where implementation details go.
|
|
This is looking really good. There was one thing I thought was worth discussing: you know how services can have a ServeHTTP method that can be used by frontend to retrieve files? I'm wondering if the transport interface could have something like Thoughts? |
|
@leaanthony oh, I didn't know that. Curious what are use-cases for it in services (why bindings are not enough). Re Should it be then Also If I understood your idea correctly, then there is For me this is not fully clean |
Think dynamic assets from v2 (outlined in tutorial here https://v3alpha.wails.io/tutorials/01-creating-a-service/#alternative-approach) it allows you to have
I haven't looked into the code fully I see it was based on my original work, there is a separate path for assets server that likely needs to be HTTP and I think the above comment could just attach to the asset server opposed to bindings transport
Agreed custom transport likely entails frontend and backend wiring |
|
@atterpac yes, this makes sence. Re
It's still there. Optional interface |
|
Yeah, it's hard to explain in text without diagrams but I'll try a use case: So the websockets example has 2 parts: the Go side and the JS side. I imagine all transports will have both as the frontend needs some kind of logic to call the Go part. By default, the HTTP transport is used for bindings so the JS side will have e.g. fetch + post etc. For websockets this code needs changing to connect to a host+socket. This JS code needs running before we can call bindings so during init. The question is whether we can fetch this JS from the backend during init rather than manually adjusting the frontend code so the host and port aren't defined in JS, but Go. Let's imagine for a minute that when the runtime starts, and requests Now that we are always requesting this file, in the message handler we can request the result of this call from the Go implementation of the transport, which is what I meant by having a method like This means that bindings transports can be completely self contained in a Go package. Let's take the example further: import "github.com/org/repo/transports/websockets"
func main() {
// .....
app := application.New(.....
// .....
Transport: websockets.New(websockets.Confg{
Host: "1.2.3.4",
Port: "8080",
// More config
},
//.....Under the hood, the config is set in the implementation, the application starts up, runtime calls This process would need to be synchronous at the start or we'd need some mechanism on the frontend to wait for that to happen if it's async via a callback or event but we'd need that anyway (what if the server is down?). I hope that all makes sense! |
|
As for the use cases in Services, think of anything that supports the service. There will be new docs uploaded soon and in that is a QR code generator tutorial. You add the service in Go, choose a route for it, then can request QR codes from the frontend using query Params, e.g. |
|
@leaanthony ok, It seems I got it. Just to double check You want to add method Am I right? If so, I can try to play around it during the week |
|
I wasn't trying to be prescriptive though. I'm open to how it works, but the idea you could import a transport in Go, add it to your service and it just works sounds like amazing DX 😉 As for global on the frontend, it doesn't have to be, that was just an example. The idea is more that the runtime has a standard interface for making the calls and that gets fulfilled by whatever |




Description
This PR refactors binding layer + provides new Transport abstraction that allow user to replace default transport with WebSockets, custom protocols, or any other transport mechanism.
Motivation:
List of changes:
/wails/runtimewith POST/wails/runtimeto handle cases with large data ([V3] CORS Error When Sending Large Data from frontend to backend service #4428)/wails/capabilitiesand/wails/flagsunder messageProcessor for object System to allow other transports handle those requests as wellresizeHandleWidthandresizeHandleHeightfor Windows were passed)Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue)
#4418
#4428
#1516
#4686
Type of change
Please select the option that is relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration using
wails doctor.If you checked Linux, please specify the distro and version.
Test Configuration
Please paste the output of
wails doctor. If you are unable to run this command, please describe your environment in as much detail as possible.Checklist:
website/src/pages/changelog.mdxwith details of this PRSummary by CodeRabbit
New Features
Documentation