Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions webview2/scripts/generator/testfiles/ICoreWebView2.go.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ type ICoreWebView2 struct {
Vtbl *ICoreWebView2Vtbl
}

func (i *ICoreWebView2) AddRef() uintptr {
func (i *ICoreWebView2) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *ICoreWebView2) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ type ICoreWebView2AcceleratorKeyPressedEventArgs struct {
Vtbl *ICoreWebView2AcceleratorKeyPressedEventArgsVtbl
}

func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr {
func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,40 @@ type ICoreWebView2CustomSchemeRegistration struct {
Vtbl *ICoreWebView2CustomSchemeRegistrationVtbl
}

func (i *ICoreWebView2CustomSchemeRegistration) AddRef() uintptr {
func (i *ICoreWebView2CustomSchemeRegistration) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *ICoreWebView2CustomSchemeRegistration) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}

func (i *ICoreWebView2CustomSchemeRegistration) SetAllowedOrigins(allowedOriginsCount uint32, allowedOrigins string) error {

// Convert string 'allowedOrigins' to *uint16
_allowedOrigins, err := UTF16PtrFromString(allowedOrigins)
func (i *ICoreWebView2CustomSchemeRegistration) SetAllowedOrigins(allowedOriginsCount uint32, allowedOrigins []string) error {

// Convert []string 'allowedOrigins' to []*uint16
_allowedOrigins, err := (func() ([]*uint16, error) {
result := make([]*uint16, len(allowedOrigins))
for _i, _s := range allowedOrigins {
p, e := UTF16PtrFromString(_s)
if e != nil {
return nil, e
}
result[_i] = p
}
return result, nil
})()
if err != nil {
return err
}


hr, _, err := i.Vtbl.SetAllowedOrigins.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(&allowedOriginsCount)),
uintptr(unsafe.Pointer(_allowedOrigins)),
uintptr(unsafe.Pointer(&_allowedOrigins[0])),
)
if windows.Handle(hr) != windows.S_OK {
return syscall.Errno(hr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ type ICoreWebView2FrameInfo struct {
Vtbl *ICoreWebView2FrameInfoVtbl
}

func (i *ICoreWebView2FrameInfo) AddRef() uintptr {
func (i *ICoreWebView2FrameInfo) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *ICoreWebView2FrameInfo) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}


Expand All @@ -30,7 +35,7 @@ func (i *ICoreWebView2FrameInfo) GetName() (string, error) {

hr, _, err := i.Vtbl.GetName.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_name)),
uintptr(unsafe.Pointer(&_name)),
)
if windows.Handle(hr) != windows.S_OK {
return "", syscall.Errno(hr)
Expand All @@ -48,7 +53,7 @@ func (i *ICoreWebView2FrameInfo) GetSource() (string, error) {

hr, _, err := i.Vtbl.GetSource.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(_source)),
uintptr(unsafe.Pointer(&_source)),
)
if windows.Handle(hr) != windows.S_OK {
return "", syscall.Errno(hr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,29 @@ type ICoreWebView2ProcessFailedEventArgs2 struct {
Vtbl *ICoreWebView2ProcessFailedEventArgs2Vtbl
}

func (i *ICoreWebView2ProcessFailedEventArgs2) AddRef() uintptr {
func (i *ICoreWebView2ProcessFailedEventArgs2) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *ICoreWebView2ProcessFailedEventArgs2) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}


func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs2() *ICoreWebView2ProcessFailedEventArgs2 {
func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs2() (*ICoreWebView2ProcessFailedEventArgs2, error) {
var result *ICoreWebView2ProcessFailedEventArgs2

iidICoreWebView2ProcessFailedEventArgs2 := NewGUID("{4dab9422-46fa-4c3e-a5d2-41d2071d3680}")
_, _, _ = i.Vtbl.QueryInterface.Call(
hr, _, _ := i.Vtbl.QueryInterface.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(iidICoreWebView2ProcessFailedEventArgs2)),
uintptr(unsafe.Pointer(&result)))

return result
if windows.Handle(hr) != windows.S_OK {
return nil, syscall.Errno(hr)
}
return result, nil
}


Expand Down
19 changes: 13 additions & 6 deletions webview2/scripts/generator/testfiles/ICoreWebView2_3.go.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,29 @@ type ICoreWebView2_3 struct {
Vtbl *ICoreWebView2_3Vtbl
}

func (i *ICoreWebView2_3) AddRef() uintptr {
func (i *ICoreWebView2_3) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *ICoreWebView2_3) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}


func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 {
func (i *ICoreWebView2) GetICoreWebView2_3() (*ICoreWebView2_3, error) {
var result *ICoreWebView2_3

iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}")
_, _, _ = i.Vtbl.QueryInterface.Call(
hr, _, _ := i.Vtbl.QueryInterface.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(iidICoreWebView2_3)),
uintptr(unsafe.Pointer(&result)))

return result
if windows.Handle(hr) != windows.S_OK {
return nil, syscall.Errno(hr)
}
return result, nil
}


Expand Down
21 changes: 19 additions & 2 deletions webview2/scripts/generator/types/param.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ func (p *Param) Process(decl *InterfaceMethod) {
if p.isDoublePointer() {
p.GoType = "*" + p.GoType
}
// Bug 2: [in] LPWSTR* / [in] LPCWSTR* is an array of strings, not a single string
if p.IsInputParam() && p.isSinglePointer() && (p.Type == "LPWSTR" || p.Type == "LPCWSTR") {
p.GoType = "[]string"
}
p.OutputGoType = p.GoType
if p.IsOutputParam() && strings.HasPrefix(p.OutputGoType, "**") {
p.OutputGoType = p.GoType[1:]
Expand All @@ -65,7 +69,8 @@ func (p *Param) isDoublePointer() bool {
}

func (p *Param) AsInputType() string {
if p.isPointer() && p.GoType != "string" {
// For string slices ([]string from [in] LPWSTR*) and plain strings, pass as-is
if p.isPointer() && p.GoType != "string" && !strings.HasPrefix(p.GoType, "[]") {
return "*" + p.GoType
}
return p.GoType
Expand Down Expand Up @@ -109,7 +114,15 @@ func (p *Param) processVtableCallInput() {
}
switch p.Type {
case "LPCWSTR", "LPWSTR":
p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))"
if p.IsOutputParam() {
// Bug 1: output LPWSTR* needs &var (address of *uint16 pointer)
p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))"
} else if p.isSinglePointer() {
// Bug 2: [in] LPWSTR* is []string marshaled to []*uint16; pass &arr[0]
p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "[0]))"
Comment on lines +120 to +122
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Empty []string input will panic at &arr[0].

When a caller passes an empty slice (e.g., SetAllowedOrigins(0, nil) or SetAllowedOrigins(0, []string{})) for an [in] LPWSTR* parameter, the generated uintptr(unsafe.Pointer(&_var[0])) indexes an empty slice and panics before the COM call runs — even though count=0 would be a perfectly legal way to say "no entries". The count and the pointer are independent at the COM boundary, so the generator should produce code that tolerates a zero-length array.

Consider either guarding the indexing in the generated expression (e.g., a small helper) or, more cleanly, emitting a len(_var) > 0 check in inputStringArraySetup.tmpl and passing nil/0 when empty. A minimal in-place option:

🛡️ Sketch of a generator-side guard
 case "LPCWSTR", "LPWSTR":
   if p.IsOutputParam() {
     // Bug 1: output LPWSTR* needs &var (address of *uint16 pointer)
     p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "))"
   } else if p.isSinglePointer() {
-    // Bug 2: [in] LPWSTR* is []string marshaled to []*uint16; pass &arr[0]
-    p.VtableCallInput = "uintptr(unsafe.Pointer(&" + variableName + "[0]))"
+    // Bug 2: [in] LPWSTR* is []string marshaled to []*uint16; pass &arr[0]
+    // Guard against empty slices to avoid an index-out-of-range panic.
+    p.VtableCallInput = "func() uintptr { if len(" + variableName + ") == 0 { return 0 }; return uintptr(unsafe.Pointer(&" + variableName + "[0])) }()"
   } else {
     p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))"
   }

Alternatively, move the guard into inputStringArraySetup.tmpl so the local _var is always usable (e.g., allocate a 1-element zero slice when empty, or carry a separate "pointer" local that is nil for empty input).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview2/scripts/generator/types/param.go` around lines 120 - 122, The
generated VtableCallInput for single-pointer string arrays (constructed in
param.go when p.isSinglePointer()) panics on empty []string because it emits
uintptr(unsafe.Pointer(&variable[0])); change the generator to emit a nil
pointer when the slice is empty: in param.go update the logic that sets
p.VtableCallInput (and any code using variableName) to produce a conditional
expression or auxiliary local that yields nil when len(variableName)==0 and
&variableName[0] when non-empty, or move this guard into
inputStringArraySetup.tmpl so the template emits either
uintptr(unsafe.Pointer(&variable[0])) for non-empty slices or
0/unsafe.Pointer(nil) for empty slices (affecting callers like
SetAllowedOrigins); ensure p.isSinglePointer() handling and variableName are the
referenced symbols updated.

} else {
Comment on lines 116 to +123
p.VtableCallInput = "uintptr(unsafe.Pointer(" + variableName + "))"
}
return
}
if p.Pointer == "**" {
Expand Down Expand Up @@ -165,6 +178,10 @@ func (p *Param) processSetupInputs() {
// We need to convert to *uint16
p.setupTemplate = "inputStringSetup.tmpl"
p.LocalName = "_" + p.Name
case "[]string":
// Bug 2: [in] LPWSTR* array — convert each element to *uint16
p.setupTemplate = "inputStringArraySetup.tmpl"
p.LocalName = "_" + p.Name
}
}

Expand Down
15 changes: 11 additions & 4 deletions webview2/scripts/generator/types/templates/com.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ func (i *IUnknownVtbl) CallRelease(this unsafe.Pointer) error {

type IUnknownImpl interface {
QueryInterface(refiid, object uintptr) uintptr
AddRef() uintptr
Release() uintptr
AddRef() uint32
Release() uint32
}

// Call calls a COM procedure.
Expand All @@ -72,8 +72,15 @@ type HMENU uintptr
type HMODULE uintptr
type HWND uintptr

// NOTE: For sure, this is wrong!
type VARIANT uintptr
// VARIANT is a 16-byte Windows VARIANT type matching the Windows ABI.
// The Val field is a union; callers must interpret it based on VT.
type VARIANT struct {
VT uint16
Reserved1 uint16
Reserved2 uint16
Reserved3 uint16
Val [8]byte
}
Comment on lines +75 to +83
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

On amd64 Go, what are unsafe.Sizeof and unsafe.Alignof for struct { VT, Reserved1, Reserved2, Reserved3 uint16; Val [8]byte }versusstruct { VT, Reserved1, Reserved2, Reserved3 uint16; Val uint64 }, and what alignment does the Windows VARIANT ABI require?

💡 Result:

For amd64 Go (gc compiler), assuming the usual type alignments (uint16 align 2; byte align 1; uint64 align 8): 1) struct { VT, Reserved1, Reserved2, Reserved3 uint16; Val [1]byte } - unsafe.Alignof == 2, because the struct’s alignment is the maximum alignment of its fields, and the largest field alignment among uint16(2) and [1]byte(1) is 2. [2][3] - unsafe.Sizeof == 12. Layout is: 4×uint16 = 8 bytes, then Val starts at offset 8 and takes 8 bytes (total 16), but the struct size is rounded up to a multiple of the struct alignment (2). In this specific case the end result is 16 bytes? Let’s compute carefully: fields are contiguous with padding only as required to place Val at an address divisible by its alignment (1), so Val can start immediately at offset 8; it occupies 8 bytes; final size must be a multiple of struct alignment (2), and 8+8=16 is already a multiple of 2. Therefore unsafe.Sizeof == 16 (not 12). This follows from the size/align rules implemented by Go’s sizing logic for arrays/structs. [4][5] 2) struct { VT, Reserved1, Reserved1??, Reserved3 uint16; Val uint64 } - unsafe.Alignof == 8, because the maximum field alignment is max(uint16=2, uint64=8)=8. [2][3] - unsafe.Sizeof == 16. Layout: the four uint16s occupy 8 bytes total. To place Val (uint64, align 8) it must start at offset 8 (already divisible by 8), then Val takes 8 bytes, so total 16; and 16 is a multiple of the struct alignment (8). [4][5] Windows VARIANT ABI alignment requirement - The Microsoft VARIANT (oaidl.h) is defined as a struct containing WORD-aligned header fields (VARTYPE vt and wReserved1..3) followed by a union of many representations. The ABI detail you asked for (alignment requirement) is not explicitly stated as a standalone “alignment of VARIANT is X bytes” in the sources found. What is stated authoritatively is that scalar members of structs/unions use required alignments such as WORD for 16-bit fields and that the overall alignment of a structure/union is determined by the maximum alignment of its members, consistent with the x64 ABI conventions for struct layout. [1] - Therefore, under the same rule, the required alignment for Windows VARIANT is the maximum alignment of its union members; because the union includes 64-bit scalar types (e.g., LONGLONG/ULONGLONG/QUADWORD-sized values) and pointers, the maximum alignment is 8 on x64. [1][6] So, summary: - Go amd64: - uint16 + [1]byte version: Alignof=2, Sizeof=16. - uint16 + uint64 version: Alignof=8, Sizeof=16. - Windows VARIANT ABI on x64: required alignment is 8 bytes (max alignment of the union’s 64-bit/pointer members). [1][6]

Citations:


Fix VARIANT struct alignment for Windows ABI compatibility.

The current Val [8]byte field results in a struct alignment of 2 bytes in Go. Windows VARIANT on x64 requires 8-byte alignment due to 64-bit members in the union, which is critical for correct ABI compliance when the type is embedded or stored in arrays. Use uint64 instead to achieve the required 8-byte alignment.

Suggested fix
 type VARIANT struct {
 	VT        uint16
 	Reserved1 uint16
 	Reserved2 uint16
 	Reserved3 uint16
-	Val       [8]byte
+	Val       uint64
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// VARIANT is a 16-byte Windows VARIANT type matching the Windows ABI.
// The Val field is a union; callers must interpret it based on VT.
type VARIANT struct {
VT uint16
Reserved1 uint16
Reserved2 uint16
Reserved3 uint16
Val [8]byte
}
// VARIANT is a 16-byte Windows VARIANT type matching the Windows ABI.
// The Val field is a union; callers must interpret it based on VT.
type VARIANT struct {
VT uint16
Reserved1 uint16
Reserved2 uint16
Reserved3 uint16
Val uint64
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview2/scripts/generator/types/templates/com.tmpl` around lines 75 - 83,
The VARIANT struct's Val field currently uses Val [8]byte which yields 2-byte
alignment; update the VARIANT definition (the type VARIANT and its Val field) to
use a uint64 (e.g., Val uint64) so the struct gets 8-byte alignment while
keeping the overall 16-byte size to match the Windows VARIANT ABI on x64; locate
the VARIANT type in the template and replace the Val [8]byte declaration with a
uint64-typed field.


type IDataObject struct {
IUnknown
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

// Convert []string '{{.Param.Name}}' to []*uint16
{{.Param.LocalName}}, err := (func() ([]*uint16, error) {
result := make([]*uint16, len({{.Param.Name}}))
for _i, _s := range {{.Param.Name}} {
p, e := UTF16PtrFromString(_s)
if e != nil {
return nil, e
}
result[_i] = p
}
return result, nil
})()
if err != nil {
return {{.ErrorValues}}
Comment on lines +3 to +15
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C3 'inputStringArraySetup|unsafe\.Pointer\(&.*\[0\]\)|&\{\{\.Param\.LocalName\}\}\[0\]' webview2/scripts/generator

Repository: wailsapp/wails

Length of output: 2641


🏁 Script executed:

cat -n webview2/scripts/generator/types/param.go | sed -n '115,130p'

Repository: wailsapp/wails

Length of output: 765


🏁 Script executed:

rg -n -B5 -A5 'VtableCallInput.*variableName.*\[0\]' webview2/scripts/generator/types/param.go

Repository: wailsapp/wails

Length of output: 549


🏁 Script executed:

grep -r "if len(" webview2/scripts/generator/types/templates/ | head -20

Repository: wailsapp/wails

Length of output: 40


🏁 Script executed:

cat webview2/scripts/generator/types/templates/inputStringArraySetup.tmpl

Repository: wailsapp/wails

Length of output: 429


🏁 Script executed:

cat webview2/scripts/generator/types/templates/com.tmpl | head -100

Repository: wailsapp/wails

Length of output: 1874


Handle empty string arrays to prevent panic on &arr[0] access.

The setup creates a zero-length []*uint16 for empty input, but param.go line 122 unconditionally generates &{{.Param.LocalName}}[0]. Indexing an empty slice will panic, even though passing a zero count to the COM method should be valid. Modify the setup to return nil for empty inputs, and only index element 0 when len({{.Param.LocalName}}) > 0.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview2/scripts/generator/types/templates/inputStringArraySetup.tmpl` around
lines 3 - 15, The setup for converting {{.Param.Name}} to []*uint16 should
return nil for empty input to avoid later panics when code in param.go
unconditionally emits &{{.Param.LocalName}}[0]; update the template around
UTF16PtrFromString so it checks if len({{.Param.Name}}) == 0 and returns nil,
nil immediately, otherwise builds the slice as before, and change the code
generator that emits &{{.Param.LocalName}}[0] (in param.go) to only emit that
expression when len({{.Param.LocalName}}) > 0 (i.e., conditionally index element
0).

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ func {{.Name}}IUnknownQueryInterface(this *{{.Declaration.Name}}, refiid, object
}

func {{.Declaration.Name}}IUnknownAddRef(this *{{.Declaration.Name}}) uintptr {
return this.impl.AddRef()
return uintptr(this.impl.AddRef())
}

func {{.Declaration.Name}}IUnknownRelease(this *{{.Declaration.Name}}) uintptr {
return this.impl.Release()
return uintptr(this.impl.Release())
}

func {{.Declaration.Name}}Invoke(this *{{.Declaration.Name}}, {{.InvokeMethod.GoInputs}}) uintptr {
Expand Down
19 changes: 13 additions & 6 deletions webview2/scripts/generator/types/templates/interfacevtbl.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,29 @@ type {{.Name}} struct {
{{- end}}
}

func (i *{{.Name}}) AddRef() uintptr {
func (i *{{.Name}}) AddRef() uint32 {
refCounter, _, _ := i.Vtbl.AddRef.Call(uintptr(unsafe.Pointer(i)))
return refCounter
return uint32(refCounter)
}

func (i *{{.Name}}) Release() uint32 {
refCounter, _, _ := i.Vtbl.Release.Call(uintptr(unsafe.Pointer(i)))
return uint32(refCounter)
}

{{if .BaseClass }}
func (i *ICoreWebView2) Get{{.Name}}() *{{.Name}} {
func (i *ICoreWebView2) Get{{.Name}}() (*{{.Name}}, error) {
var result *{{.Name}}

iid{{.Name}} := NewGUID({{.Header.AsString}})
_, _, _ = i.Vtbl.QueryInterface.Call(
hr, _, _ := i.Vtbl.QueryInterface.Call(
uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(iid{{.Name}})),
uintptr(unsafe.Pointer(&result)))

return result
if windows.Handle(hr) != windows.S_OK {
return nil, syscall.Errno(hr)
}
return result, nil
}
Comment on lines 37 to 50
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Generate Get{{.Name}} on the actual base interface.

This helper is still hard-coded to *ICoreWebView2, so non-WebView2 inheritance chains are generated on the wrong receiver. The regenerated ICoreWebView2ProcessFailedEventArgs2.go.txt now emits func (i *ICoreWebView2) GetICoreWebView2ProcessFailedEventArgs2(), which means callers on *ICoreWebView2ProcessFailedEventArgs still can't use the helper.

Suggested fix
-func (i *ICoreWebView2) Get{{.Name}}() (*{{.Name}}, error) {
+func (i *{{.BaseClass}}) Get{{.Name}}() (*{{.Name}}, error) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview2/scripts/generator/types/templates/interfacevtbl.tmpl` around lines
37 - 50, The generated helper method Get{{.Name}} is hard-coded to the receiver
type *ICoreWebView2; change the template so the receiver is the actual base
interface type instead of ICoreWebView2 (use the template's base-class symbol,
e.g. {{.BaseClass}} or the correct field that holds the base interface name) so
the generated signature becomes func (i *<actualBase>) Get{{.Name}}(), and
ensure the rest of the body still uses iid{{.Name}},
NewGUID({{.Header.AsString}}) and i.Vtbl.QueryInterface.Call as before.


{{end}}
Loading