Repository navigation
[V3] Refactor binding transport layer - #4702
Conversation
WalkthroughIntroduces a pluggable IPC transport layer (Transport interfaces, HTTP and WebSocket transports), refactors runtime and message processing from HTTP-centric handlers to a RuntimeRequest-driven model, adds a typed errs package with codegen, and includes a WebSocket transport example with generated frontend bindings and runtime API changes. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant FE as Frontend (runtime.ts / JS)
participant RT as Runtime API (runtime.ts)
participant TR as Transport (HTTPTransport / WebSocketTransport)
participant MP as MessageProcessor (server)
participant APP as App handlers (process* methods)
FE->>RT: call(object, method, args)
RT->>RT: if customTransport set?
alt custom transport available
RT->>TR: transport.call(object, method, window, args)
else
RT->>TR: HTTP POST /wails/runtime (default transport)
end
TR->>MP: HandleRuntimeCallWithIDs(ctx, RuntimeRequest)
MP->>APP: route by object -> processX(req)
APP-->>MP: (result, error)
MP-->>TR: response payload / error
TR-->>RT: transport response
RT-->>FE: resolve promise (result or error)
Estimated code review effort🎯 5 (Critical) | ⏱️ ~150 minutes
Possibly related PRs
Suggested labels
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 ignored due to path filters (1)
📒 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). (4)
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.
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.
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.
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.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
v3/UNRELEASED_CHANGELOG.md(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). (4)
- 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)
- GitHub Check: semgrep-cloud-platform/scan
|
@leaanthony I spent some time looking into this option, and my personal opinion is that we should keep things as they are. Adding JSClient would just introduce another way to solve the same task without providing clear benefits. We can already pass any “args” or “transport params” through Flags. And if someone wants to serve a client from the transport layer, TransportHTTPHandler already allows adding custom routes. I experimented with this in a separate branch — you can see the examples in this PR: https://github.com/APshenkin/wails/pull/2/files Practically speaking, if I were implementing a custom transport for an app, I’d build it together with the app using the same tooling. Creating a separate /wails/transport.js would require an additional build pipeline just to serve that file from /wails/transport.js. What do you think? |
|
@APshenkin - thanks for taking the time to look at that. I appreciate your efforts 🙏 I think there may be some cross-wires here though. Perhaps it would be easier for me to ask a question: If someone wanted to reuse the websocket transport (or any transport) in their project, how would they do that? |
|
@leaanthony
or simplest – copy it in your project |
|
@leaanthony anything that blocks us to merge this PR? Happy to work on it. if you still want to add JSClient, can do so, as heavy lifting for it is very low. |
|
@APshenkin thanks for your patience. I wanted to try and review the last files. It mainly looks good to me and thanks again for taking on such an epic PR 🙏 The thing I was trying to convey before was whether this code: const { setTransport } = await import('/wails/runtime.js');
class MyRuntimeTransport {
call(objectID: number, method: number, windowName: string, args: any): Promise<any> {
// TODO: implement IPC call with your transport protocol
return resp;
}
}
const myTransport = new MyRuntimeTransport();
setTransport(myTransport);could be automatic instead of something that people will need to copy and paste in. Like this could be in the runtime by default: let transport = await fetch("/wails/transport")
setTransport(transport)Which means your transport module would be able to service the frontend dynamically by handling Does this make any sense? It's been a loooong day 😅 |
|
@leaanthony added. Tell what you think about it |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
v3/examples/websocket-transport/assets/index.html (2)
328-340:setIntervalcreated on line 331 is never cleared, causing a potential memory leak.The status polling interval runs indefinitely even after the module/page unloads. For a long-running app or single-page app with navigation, this will accumulate intervals.
Store the interval ID and clear it when the transport is destroyed or the page unloads:
- function updateConnectionStatus() { - const statusEl = document.getElementById("connection-status"); - - setInterval(() => { + function updateConnectionStatus() { + const statusEl = document.getElementById("connection-status"); + const intervalId = setInterval(() => { if (transport.isConnected()) { statusEl.innerHTML = "<span class=\"status connected\">✓ Connected to WebSocket (ws://localhost:9099)</span>"; } else { statusEl.innerHTML = "<span class=\"status disconnected\">✗ Disconnected</span>"; } }, 1000); + + // Cleanup on page unload + window.addEventListener("beforeunload", () => clearInterval(intervalId)); }
169-169: Hardcoded WebSocket endpoint in display text may become stale.The info text on line 169 hardcodes
ws://localhost:9099/wails/ws. If the transport or port changes, this text requires manual updates. Consider extracting the endpoint from the transport object or documenting it prominently.Derive the endpoint from the transport object at runtime (if the transport exposes it):
- instead of the default HTTP fetch-based transport. All Wails <strong>generated bindings</strong> work identically! + instead of the default HTTP fetch-based transport. All Wails <strong>generated bindings</strong> work identically!<br> + <span id="endpointDisplay"></span>Then, after importing the transport, populate the endpoint dynamically (if available on the transport object).
v3/pkg/application/transport_http.go (1)
114-121: Use field names inArgscomposite literal for robustness.
Argscurrently has a single unexported field (rawData), but the literal&Args{body.Args}depends on field order. This is fragile ifArgsever gains additional fields.Prefer a field‑named literal to make the intent explicit and future‑proof:
- Args: &Args{body.Args}, + Args: &Args{rawData: body.Args},
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
v3/examples/websocket-transport/assets/index.html(1 hunks)v3/examples/websocket-transport/transport_websocket.go(1 hunks)v3/examples/websocket-transport/websocket-transport.js(1 hunks)v3/pkg/application/application.go(2 hunks)v3/pkg/application/transport.go(1 hunks)v3/pkg/application/transport_http.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- v3/examples/websocket-transport/transport_websocket.go
- v3/pkg/application/transport.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-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
📚 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-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-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/websocket-transport.js
🧬 Code graph analysis (2)
v3/pkg/application/application.go (6)
v3/pkg/application/transport.go (2)
Transport(18-28)TransportHTTPHandler(65-67)v3/pkg/application/transport_http.go (2)
NewHTTPTransport(20-31)HTTPTransportWithLogger(37-41)v3/pkg/application/transport_event_ipc.go (1)
EventIPCTransport(3-5)v3/internal/assetserver/middleware.go (2)
Middleware(10-10)ChainMiddleware(13-20)v3/internal/assetserver/common.go (1)
ServeFile(29-40)v3/internal/assetserver/options.go (1)
Options(10-29)
v3/pkg/application/transport_http.go (3)
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)
⏰ 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 (ubuntu-latest, 1.24)
- GitHub Check: Run Go Tests v3 (macos-latest, 1.24)
- GitHub Check: Run Go Tests v3 (windows-latest, 1.24)
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
v3/examples/websocket-transport/assets/index.html (1)
237-251: Transport and runtime initialization follows new abstraction pattern correctly.The cache-buster on line 241 and proper error boundary on lines 238–350 are good practices for an example. The transport-to-runtime wiring via
setTransport()aligns well with the PR's pluggable transport design.v3/examples/websocket-transport/websocket-transport.js (1)
82-105: Avoid auto‑reconnect after an explicitclose()call.
ws.onclosealways schedules a reconnect, even when the connection was closed intentionally viaclose(). This makes it impossible for callers (or the runtime) to reliably shut down the transport; a manual close just triggers the reconnect loop again.Consider tracking manual closes and skipping reconnect in that case, for example:
export class WebSocketTransport { constructor(url, options = {}) { this.url = url; this.ws = null; this.wsReady = false; this.pendingRequests = new Map(); this.messageQueue = []; this.reconnectTimer = null; + this.manualClose = false; @@ close() { - if (this.reconnectTimer) { - clearTimeout(this.reconnectTimer); - this.reconnectTimer = null; - } - - if (this.ws) { - this.ws.close(); - this.ws = null; - } - - this.wsReady = false; + this.manualClose = true; + if (this.reconnectTimer) { + clearTimeout(this.reconnectTimer); + this.reconnectTimer = null; + } + if (this.ws) { + this.ws.close(); + this.ws = null; + } + this.wsReady = false; } @@ this.ws.onclose = () => { console.log("[WebSocket] Disconnected"); this.wsReady = false; @@ - // Attempt to reconnect - if (!this.reconnectTimer) { + if (this.manualClose) { + // One-shot: don't reconnect after an explicit close. + this.manualClose = false; + return; + } + + // Attempt to reconnect after unexpected disconnects + if (!this.reconnectTimer) { this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; console.log("[WebSocket] Attempting to reconnect..."); this.connect().catch(err => { console.error("[WebSocket] Reconnection failed:", err); }); }, this.reconnectDelay); } };Also applies to: 213-225
v3/pkg/application/application.go (1)
82-99: PreserveOnShutdowncallback ordering (user hook first, then transport stop).
cleanup()runsshutdownTasksin the order they were added, and the comment onshutdownTaskssays the application optionOnShutdownruns first. Currently:
- The transport stop hook is added via
result.OnShutdown(func() { transport.Stop() })(Line 93).- The user‑supplied
appOptions.OnShutdownhook is added later (Lines 176–178).This inverts the documented order and means user
OnShutdownnow runs after the transport has been stopped, which can surprise apps that want to interact with the transport/runtime during shutdown.Consider registering the user hook before the transport stop hook:
- // Register shutdown task to stop transport - result.OnShutdown(func() { - if err := transport.Stop(); err != nil { - result.error("failed to stop custom transport: %w", err) - } - }) @@ - if appOptions.OnShutdown != nil { - result.OnShutdown(appOptions.OnShutdown) - } + if appOptions.OnShutdown != nil { + result.OnShutdown(appOptions.OnShutdown) + } + + // Register shutdown task to stop transport after user hook + result.OnShutdown(func() { + if err := transport.Stop(); err != nil { + result.error("failed to stop custom transport: %w", err) + } + })This keeps the documented contract and gives user shutdown logic access to a still‑running transport.
|
@leaanthony did you had a chance to take a look? Anything that I can help with this PR |
|
|
@APshenkin - Thanks for your patience. I'm good for this to go as is. I think there might be some tweaks but that can come later and definitely don't want to block such an epic PR 👍 🙏 |
This commit integrates iOS platform support for Wails v3, adapting the iOS-specific code to work with the new transport layer architecture. Key changes: - Add iOS-specific application, webview, and runtime files - Add iOS event types and processing - Add iOS examples and templates - Update messageprocessor to handle iOS requests - Move badge_ios.go to dock package Note: The iOS branch was based on an older v3-alpha and required significant conflict resolution due to the transport layer refactor (PR #4702). Some iOS-specific code may need further adaptation: - processIOSMethod needs to be implemented with new RuntimeRequest signature - iOS event generation in tasks/events/generate.go needs updating 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* custom transport initial * transport codecs * runtime set transport * events transport * clauded example * bundled runtime * wip: transport * rework transports * rework dialog responses * cleanup * cleanup * improve error handling in HTTPTransport * cleanup * cleanup * cleanup * cleanup * review changes * review changes * review changes * review changes * review changes * review changes * review changes * move documentation to website docs * update doc * update changelog * introduce JSClient method for transport for embedding JS part in transport --------- Co-authored-by: Atterpac <Capretta.Michael@gmail.com> Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit integrates iOS platform support for Wails v3, adapting the iOS-specific code to work with the new transport layer architecture. Key changes: - Add iOS-specific application, webview, and runtime files - Add iOS event types and processing - Add iOS examples and templates - Update messageprocessor to handle iOS requests - Move badge_ios.go to dock package Note: The iOS branch was based on an older v3-alpha and required significant conflict resolution due to the transport layer refactor (PR wailsapp#4702). Some iOS-specific code may need further adaptation: - processIOSMethod needs to be implemented with new RuntimeRequest signature - iOS event generation in tasks/events/generate.go needs updating 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>




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
Refactor
New Utilities
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.