diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 180057d45..84b7cb6dc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -7,7 +7,7 @@ body:
- type: markdown
attributes:
value: |
- ***Please note: No new bug reports are being accepted for Wails v1***
+ ***Please note: No bug reports are currently being accepted for Wails v3***
Before submitting this issue, please do the following:
- Do a web search for your error. This usually leads to a much better understanding of the issue.
- Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce.
@@ -84,4 +84,4 @@ body:
description: Add any other context about the problem here.
placeholder: Add any other context about the problem here.
validations:
- required: false
\ No newline at end of file
+ required: false
diff --git a/.github/workflows/format-markdown-files.yml b/.github/workflows/format-markdown-files.yml
deleted file mode 100644
index d30546428..000000000
--- a/.github/workflows/format-markdown-files.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: Format Markdown Files
-
-on:
- workflow_dispatch:
- push:
- branches: [master]
-
-jobs:
- format_markdown_files:
- runs-on: ubuntu-latest
- if: github.repository == 'wailsapp/wails'
- steps:
- - uses: actions/checkout@v3
-
- - name: Setup Nodejs
- uses: actions/setup-node@v2
- with:
- node-version: 18.x
-
- - name: Install Task
- uses: arduino/setup-task@v1
- with:
- version: 3.x
- repo-token: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Format All Markdown Files
- run: task format-all-md
-
- - name: Create Pull Request
- uses: peter-evans/create-pull-request@v4
- with:
- commit-message: "docs: format document"
- title: "docs: format document"
- body: "- [x] Format all Markdown(x) documents"
- branch: chore/format-markdown-files
- delete-branch: true
- draft: false
diff --git a/README.es.md b/README.es.md
new file mode 100644
index 000000000..47c932285
--- /dev/null
+++ b/README.es.md
@@ -0,0 +1,167 @@
+
+
+
+
+
+ Construye aplicaciones de escritorio usando Go y tecnologías web.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md)
+
+
+
+
+
+## Tabla de Contenidos
+
+- [Tabla de Contenidos](#tabla-de-contenidos)
+- [Introducción](#introducción)
+- [Funcionalidades](#funcionalidades)
+ - [Plan de Trabajo](#plan-de-trabajo)
+- [Empezando](#empezando)
+- [Patrocinadores](#patrocinadores)
+- [Preguntas Frecuentes](#preguntas-frecuentes)
+- [Estrellas a lo Largo del Tiempo](#estrellas-a-lo-largo-del-tiempo)
+- [Colaboradores](#colaboradores)
+- [Licencia](#licencia)
+- [Inspiración](#inspiración)
+
+## Introducción
+
+El método tradicional para proveer una interfaz web en programas hechos con Go
+es a través del servidor web incorporado. Wails ofrece un enfoque diferente al
+permitir combinar el código hecho en Go con un frontend web en un solo archivo
+binario. Las herramientas que proporcionamos facilitan este trabajo para ti, al
+crear, compilar y empaquetar tu proyecto. ¡Lo único que debes hacer es ponerte
+creativo!
+
+## Funcionalidades
+
+- Utiliza Go estándar para el backend
+- Utiliza cualquier tecnología frontend con la que ya estés familiarizado para
+ construir tu interfaz de usuario
+- Crea rápidamente interfaces de usuario enriquecidas para tus programas en Go
+ utilizando plantillas predefinidas
+- Invoca fácilmente métodos de Go desde Javascript
+- Definiciones de Typescript generadas automáticamente para tus structs y
+ métodos de Go
+- Diálogos y menús nativos
+- Soporte nativo de modo oscuro / claro
+- Soporte de translucidez y efectos de ventana esmerilada
+- Sistema de eventos unificado entre Go y Javascript
+- Herramienta CLI potente para generar y construir tus proyectos rápidamente
+- Multiplataforma
+- Usa motores de renderizado nativos - ¡_sin navegador integrado_!
+
+### Plan de Trabajo
+
+El plan de trabajo se puede encontrar
+[aqui](https://github.com/wailsapp/wails/discussions/1484). Por favor,
+consúltalo antes de abrir una solicitud de mejora.
+
+## Empezando
+
+Las instrucciones de instalacion se encuentran en nuestra
+[pagina web oficial](https://wails.io/docs/gettingstarted/installation).
+
+## Patrocinadores
+
+Este Proyecto cuenta con el apoyo de estas amables personas/ compañías:
+
+
+
+
+
+
+## Preguntas Frecuentes
+
+- ¿Es esta una alternativa a Electron?
+
+ Depende de tus requisitos. Está diseñado para facilitar a los programadores de
+ Go la creación de aplicaciones de escritorio livianas o agregar una interfaz
+ gráfica a sus aplicaciones existentes. Wails ofrece elementos nativos como
+ menús y diálogos, por lo que podría considerarse una alternativa liviana a
+ Electron.
+
+- ¿A quien esta dirigido este proyecto?
+
+ El proyecto esta dirigido a programadores de Go que desean integrar una
+ interfaz HMTL/JS/CSS en sus aplicaciones, sin tener que recurrir a la creación
+ de un servidor y abrir el navegador para visualizarla.
+
+- ¿Cual es el significado del nombre?
+
+ Cuando vi WebView, pensé: "Lo que realmente quiero es una herramienta para
+ construir una aplicación WebView, algo similar a lo que Rails es para Ruby".
+ Así que inicialmente fue un juego de palabras (WebView en Rails). Además, por
+ casualidad, también es homófono del nombre en inglés del
+ [país](https://en.wikipedia.org/wiki/Wales) del que provengo. Así que se quedó
+ con ese nombre.
+
+## Estrellas a lo Largo del Tiempo
+
+[](https://star-history.com/#wailsapp/wails&Date)
+
+## Colaboradores
+
+¡La lista de colaboradores se está volviendo demasiado grande para el archivo
+readme! Todas las personas increíbles que han contribuido a este proyecto tienen
+su propia página [aqui](https://wails.io/credits#contributors).
+
+## Licencia
+
+[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
+
+## Inspiración
+
+Este proyecto fue construido mientras se escuchaban estos álbumes:
+
+- [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
+- [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
+- [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
+- [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
+- [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
+- [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
+- [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
+- [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
+- [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
+- [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
+- [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
+- [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
+- [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
+ [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
diff --git a/README.ja.md b/README.ja.md
index f308fd754..85fbc48f4 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -42,7 +42,8 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md)
diff --git a/README.ko.md b/README.ko.md
index 441b77f66..a87fa3264 100644
--- a/README.ko.md
+++ b/README.ko.md
@@ -42,7 +42,8 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md)
diff --git a/README.md b/README.md
index 5910be650..dfb84a014 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,8 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md)
diff --git a/README.zh-Hans.md b/README.zh-Hans.md
index 69d456e78..de306f8a5 100644
--- a/README.zh-Hans.md
+++ b/README.zh-Hans.md
@@ -42,7 +42,8 @@
-[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) · [한국어](README.ko.md)
+[English](README.md) · [简体中文](README.zh-Hans.md) · [日本語](README.ja.md) ·
+[한국어](README.ko.md) · [Español](README.es.md)
@@ -87,7 +88,7 @@
## 快速入门
-使用说明在 [官网](https://wails.io/docs/gettingstarted/installation)。
+使用说明在 [官网](https://wails.io/zh-Hans/docs/gettingstarted/installation/)。
## 赞助商
diff --git a/scripts/sponsors/package-lock.json b/scripts/sponsors/package-lock.json
index 30997a31a..5153e9cf8 100644
--- a/scripts/sponsors/package-lock.json
+++ b/scripts/sponsors/package-lock.json
@@ -13,9 +13,12 @@
}
},
"node_modules/@antfu/utils": {
- "version": "0.5.2",
- "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.5.2.tgz",
- "integrity": "sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA=="
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.4.tgz",
+ "integrity": "sha512-qe8Nmh9rYI/HIspLSTwtbMFPj6dISG6+dJnOguTlPNXtCvS2uezdxscVBb7/3DrmNbQK49TDqpkSQ1chbRGdpQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
},
"node_modules/ajv": {
"version": "6.12.6",
@@ -419,9 +422,9 @@
}
},
"node_modules/defu": {
- "version": "6.1.1",
- "resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.1.tgz",
- "integrity": "sha512-aA964RUCsBt0FGoNIlA3uFgo2hO+WWC0fiC6DBps/0SFzkKcYoM/3CzVLIa5xSsrFjdioMdYgAIbwo80qp2MoA=="
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz",
+ "integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ=="
},
"node_modules/delayed-stream": {
"version": "1.0.0",
@@ -951,9 +954,9 @@
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
},
"node_modules/jiti": {
- "version": "1.16.0",
- "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.16.0.tgz",
- "integrity": "sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==",
+ "version": "1.18.2",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz",
+ "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==",
"bin": {
"jiti": "bin/jiti.js"
}
@@ -1443,9 +1446,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "version": "7.5.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
+ "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -1765,13 +1768,16 @@
"integrity": "sha512-fk6CmUgwKCfX79EzcDQQpSCMxrHstvbLswFChHS0Vump+kFkw7nJBfTZoC1j0bOGoY9I7R3n2DGek5ajbcYnOw=="
},
"node_modules/unconfig": {
- "version": "0.3.7",
- "resolved": "https://registry.npmmirror.com/unconfig/-/unconfig-0.3.7.tgz",
- "integrity": "sha512-1589b7oGa8ILBYpta7TndM5mLHLzHUqBfhszeZxuUBrjO/RoQ52VGVWsS3w0C0GLNxO9RPmqkf6BmIvBApaRdA==",
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.3.9.tgz",
+ "integrity": "sha512-8yhetFd48M641mxrkWA+C/lZU4N0rCOdlo3dFsyFPnBHBjMJfjT/3eAZBRT2RxCRqeBMAKBVgikejdS6yeBjMw==",
"dependencies": {
- "@antfu/utils": "^0.5.2",
- "defu": "^6.1.0",
- "jiti": "^1.16.0"
+ "@antfu/utils": "^0.7.2",
+ "defu": "^6.1.2",
+ "jiti": "^1.18.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
}
},
"node_modules/undici": {
diff --git a/v2/cmd/wails/build.go b/v2/cmd/wails/build.go
index 5d284e9a2..1c6b791ec 100644
--- a/v2/cmd/wails/build.go
+++ b/v2/cmd/wails/build.go
@@ -57,6 +57,7 @@ func buildApplication(f *flags.Build) error {
OutputFile: f.OutputFilename,
CleanBinDirectory: f.Clean,
Mode: f.GetBuildMode(),
+ Devtools: f.Debug || f.Devtools,
Pack: !f.NoPackage,
LDFlags: f.LdFlags,
Compiler: f.Compiler,
@@ -82,6 +83,7 @@ func buildApplication(f *flags.Build) error {
{"Compiler", f.GetCompilerPath()},
{"Skip Bindings", bool2Str(f.SkipBindings)},
{"Build Mode", f.GetBuildModeAsString()},
+ {"Devtools", bool2Str(buildOptions.Devtools)},
{"Frontend Directory", projectOptions.GetFrontendDir()},
{"Obfuscated", bool2Str(f.Obfuscated)},
}
diff --git a/v2/cmd/wails/flags/build.go b/v2/cmd/wails/flags/build.go
index d36ceef6a..974d9c3ad 100644
--- a/v2/cmd/wails/flags/build.go
+++ b/v2/cmd/wails/flags/build.go
@@ -35,6 +35,7 @@ type Build struct {
ForceBuild bool `name:"f" description:"Force build of application"`
UpdateWailsVersionGoMod bool `name:"u" description:"Updates go.mod to use the same Wails version as the CLI"`
Debug bool `description:"Builds the application in debug mode"`
+ Devtools bool `description:"Enable Devtools in productions, Already enabled in debug mode (-debug)"`
NSIS bool `description:"Generate NSIS installer for Windows"`
TrimPath bool `description:"Remove all file system paths from the resulting executable"`
WindowsConsole bool `description:"Keep the console when building for Windows"`
diff --git a/v2/cmd/wails/flags/dev.go b/v2/cmd/wails/flags/dev.go
index 885e0cead..6d4f02f95 100644
--- a/v2/cmd/wails/flags/dev.go
+++ b/v2/cmd/wails/flags/dev.go
@@ -120,6 +120,7 @@ func (d *Dev) GenerateBuildOptions() *build.Options {
result := &build.Options{
OutputType: "dev",
Mode: build.Dev,
+ Devtools: true,
Arch: runtime.GOARCH,
Pack: true,
Platform: runtime.GOOS,
diff --git a/v2/examples/customlayout/build/windows/installer/project.nsi b/v2/examples/customlayout/build/windows/installer/project.nsi
index 3b1588e0c..2ccc0f3f3 100644
--- a/v2/examples/customlayout/build/windows/installer/project.nsi
+++ b/v2/examples/customlayout/build/windows/installer/project.nsi
@@ -45,6 +45,9 @@ VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
+# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
+ManifestDPIAware true
+
!include "MUI.nsh"
!define MUI_ICON "..\icon.ico"
diff --git a/v2/go.mod b/v2/go.mod
index a323c32d1..a83fc12ff 100644
--- a/v2/go.mod
+++ b/v2/go.mod
@@ -13,33 +13,33 @@ require (
github.com/go-git/go-git/v5 v5.3.0
github.com/go-ole/go-ole v1.2.6
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
- github.com/google/uuid v1.1.2
+ github.com/google/uuid v1.3.0
github.com/jackmordaunt/icns v1.0.0
- github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e
- github.com/labstack/echo/v4 v4.9.0
- github.com/labstack/gommon v0.3.1
+ github.com/labstack/echo/v4 v4.10.2
+ github.com/labstack/gommon v0.4.0
github.com/leaanthony/clir v1.3.0
github.com/leaanthony/debme v1.2.1
- github.com/leaanthony/go-ansi-parser v1.0.1
+ github.com/leaanthony/go-ansi-parser v1.6.0
github.com/leaanthony/gosod v1.0.3
- github.com/leaanthony/slicer v1.5.0
+ github.com/leaanthony/slicer v1.6.0
github.com/leaanthony/winicon v1.0.0
github.com/matryer/is v1.4.0
- github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2
+ github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.49
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
- github.com/samber/lo v1.27.1
- github.com/stretchr/testify v1.8.0
+ github.com/samber/lo v1.38.1
+ github.com/stretchr/testify v1.8.1
github.com/tc-hib/winres v0.1.5
github.com/tidwall/sjson v1.1.7
- github.com/tkrajina/go-reflector v0.5.5
+ github.com/tkrajina/go-reflector v0.5.6
+ github.com/wailsapp/go-webview2 v1.0.1
github.com/wailsapp/mimetype v1.4.1
github.com/wzshiming/ctc v1.2.3
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
- golang.org/x/net v0.7.0
- golang.org/x/sys v0.5.0
- golang.org/x/tools v0.1.12
+ golang.org/x/mod v0.8.0
+ golang.org/x/net v0.10.0
+ golang.org/x/sys v0.8.0
+ golang.org/x/tools v0.6.0
)
require (
@@ -59,12 +59,13 @@ require (
github.com/gorilla/css v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/microcosm-cc/bluemonday v1.0.17 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
@@ -73,23 +74,23 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/rivo/uniseg v0.4.4 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/tidwall/gjson v1.9.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
+ github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
github.com/yuin/goldmark v1.4.13 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect
- golang.org/x/crypto v0.1.0 // indirect
- golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
+ golang.org/x/crypto v0.9.0 // indirect
+ golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/image v0.5.0 // indirect
- golang.org/x/term v0.5.0 // indirect
- golang.org/x/text v0.7.0 // indirect
+ golang.org/x/term v0.8.0 // indirect
+ golang.org/x/text v0.9.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/v2/go.sum b/v2/go.sum
index 1eb919839..5c8c5a5c0 100644
--- a/v2/go.sum
+++ b/v2/go.sum
@@ -67,12 +67,12 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
-github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
-github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
@@ -103,21 +103,22 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
-github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
+github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
+github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
+github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0=
github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
-github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
-github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
+github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg=
+github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
-github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
+github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
+github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
@@ -126,11 +127,14 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
@@ -148,8 +152,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
-github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -165,14 +169,15 @@ github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkG
github.com/pterm/pterm v0.12.49 h1:qeNm0wTWawy6WhKoY8ZKq6qTXFr0s2UtUyRW0yVztEg=
github.com/pterm/pterm v0.12.49/go.mod h1:D4OBoWNqAfXkm5QLTjIgjNiMXPHemLJHnIreGUsWzWg=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
-github.com/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg=
-github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
+github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
+github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -180,16 +185,17 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tc-hib/winres v0.1.5 h1:2dA5yfjdoEA3UyRaOC92HNMt3jap66pLzoW4MjpC/0M=
github.com/tc-hib/winres v0.1.5/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
-github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E=
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@@ -201,12 +207,15 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8=
github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs=
-github.com/tkrajina/go-reflector v0.5.5 h1:gwoQFNye30Kk7NrExj8zm3zFtrGPqOkzFMLuQZg1DtQ=
-github.com/tkrajina/go-reflector v0.5.5/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
+github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/wailsapp/go-webview2 v1.0.1 h1:dEJIeEApW/MhO2tTMISZBFZPuW7kwrFA1NtgFB1z1II=
+github.com/wailsapp/go-webview2 v1.0.1/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c=
@@ -227,26 +236,28 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
-golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
+golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
+golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
-golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -271,24 +282,28 @@ golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/v2/internal/app/app.go b/v2/internal/app/app.go
index f2821aaba..226b5a0be 100644
--- a/v2/internal/app/app.go
+++ b/v2/internal/app/app.go
@@ -2,6 +2,7 @@ package app
import (
"context"
+
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/menumanager"
@@ -20,6 +21,9 @@ type App struct {
// Indicates if the app is in debug mode
debug bool
+ // Indicates if the devtools is enabled
+ devtools bool
+
// OnStartup/OnShutdown
startupCallback func(ctx context.Context)
shutdownCallback func(ctx context.Context)
diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go
index 38aada698..2e04f448b 100644
--- a/v2/internal/app/app_dev.go
+++ b/v2/internal/app/app_dev.go
@@ -42,7 +42,9 @@ func (a *App) Run() error {
func CreateApp(appoptions *options.App) (*App, error) {
var err error
- ctx := context.WithValue(context.Background(), "debug", true)
+ ctx := context.Background()
+ ctx = context.WithValue(ctx, "debug", true)
+ ctx = context.WithValue(ctx, "devtools", true)
// Set up logger
myLogger := logger.New(appoptions.Logger)
@@ -211,7 +213,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
eventHandler := runtime.NewEvents(myLogger)
ctx = context.WithValue(ctx, "events", eventHandler)
- messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler)
+ messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter)
// Create the frontends and register to event handler
desktopFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
@@ -228,6 +230,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
startupCallback: appoptions.OnStartup,
shutdownCallback: appoptions.OnShutdown,
debug: true,
+ devtools: true,
}
result.options = appoptions
diff --git a/v2/internal/app/app_devtools.go b/v2/internal/app/app_devtools.go
new file mode 100644
index 000000000..e28a1e080
--- /dev/null
+++ b/v2/internal/app/app_devtools.go
@@ -0,0 +1,7 @@
+//go:build devtools
+
+package app
+
+func IsDevtoolsEnabled() bool {
+ return true
+}
diff --git a/v2/internal/app/app_devtools_not.go b/v2/internal/app/app_devtools_not.go
new file mode 100644
index 000000000..a2cfd4e5d
--- /dev/null
+++ b/v2/internal/app/app_devtools_not.go
@@ -0,0 +1,7 @@
+//go:build !devtools
+
+package app
+
+func IsDevtoolsEnabled() bool {
+ return false
+}
diff --git a/v2/internal/app/app_production.go b/v2/internal/app/app_production.go
index afb67bdb3..5b847260c 100644
--- a/v2/internal/app/app_production.go
+++ b/v2/internal/app/app_production.go
@@ -34,7 +34,9 @@ func CreateApp(appoptions *options.App) (*App, error) {
options.MergeDefaults(appoptions)
debug := IsDebug()
+ devtools := IsDevtoolsEnabled()
ctx = context.WithValue(ctx, "debug", debug)
+ ctx = context.WithValue(ctx, "devtools", devtools)
// Set up logger
myLogger := logger.New(appoptions.Logger)
@@ -80,7 +82,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
ctx = context.WithValue(ctx, "buildtype", "production")
}
- messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler)
+ messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter)
appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
eventHandler.AddFrontend(appFrontend)
@@ -93,6 +95,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
startupCallback: appoptions.OnStartup,
shutdownCallback: appoptions.OnShutdown,
debug: debug,
+ devtools: devtools,
options: appoptions,
}
diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h
index e418168e6..4239da93b 100644
--- a/v2/internal/frontend/desktop/darwin/Application.h
+++ b/v2/internal/frontend/desktop/darwin/Application.h
@@ -17,7 +17,7 @@
#define WindowStartsMinimised 2
#define WindowStartsFullscreen 3
-WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled);
+WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtools, int defaultContextMenu, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled);
void Run(void*, const char* url);
void SetTitle(void* ctx, const char *title);
diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m
index ab951714d..2c08002d4 100644
--- a/v2/internal/frontend/desktop/darwin/Application.m
+++ b/v2/internal/frontend/desktop/darwin/Application.m
@@ -13,13 +13,14 @@
#import "WailsMenu.h"
#import "WailsMenuItem.h"
-WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled) {
+WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtools, int defaultContextMenu, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled) {
[NSApplication sharedApplication];
WailsContext *result = [WailsContext new];
- result.debug = debug;
+ result.devtools = devtools;
+ result.defaultContextMenu = defaultContextMenu;
if ( windowStartState == WindowStartsFullscreen ) {
fullscreen = 1;
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.h b/v2/internal/frontend/desktop/darwin/WailsContext.h
index 1e48b2182..7cdf034bb 100644
--- a/v2/internal/frontend/desktop/darwin/WailsContext.h
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.h
@@ -44,7 +44,8 @@
@property bool alwaysOnTop;
-@property bool debug;
+@property bool devtools;
+@property bool defaultContextMenu;
@property (retain) WKUserContentController* userContentController;
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.m b/v2/internal/frontend/desktop/darwin/WailsContext.m
index 29fa99317..cc5aa2349 100644
--- a/v2/internal/frontend/desktop/darwin/WailsContext.m
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.m
@@ -225,12 +225,12 @@ typedef void (^schemeTaskCaller)(id);
[userContentController addScriptMessageHandler:self name:@"external"];
config.userContentController = userContentController;
self.userContentController = userContentController;
- if (self.debug) {
+ if (self.devtools) {
[config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
- } else {
+ } else if (!self.defaultContextMenu) {
// Disable default context menus
WKUserScript *initScript = [WKUserScript new];
- [initScript initWithSource:@"window.wails.flags.disableWailsDefaultContextMenu = true;"
+ [initScript initWithSource:@"window.wails.flags.disableDefaultContextMenu = true;"
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:false];
[userContentController addUserScript:initScript];
diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go
index b714a2c3b..c0dd27029 100644
--- a/v2/internal/frontend/desktop/darwin/frontend.go
+++ b/v2/internal/frontend/desktop/darwin/frontend.go
@@ -47,6 +47,7 @@ type Frontend struct {
frontendOptions *options.App
logger *logger.Logger
debug bool
+ devtools bool
// Assets
assets *assetserver.AssetServer
@@ -151,12 +152,18 @@ func (f *Frontend) WindowSetDarkTheme() {
func (f *Frontend) Run(ctx context.Context) error {
f.ctx = ctx
+
var _debug = ctx.Value("debug")
+ var _devtools = ctx.Value("devtools")
+
if _debug != nil {
f.debug = _debug.(bool)
}
+ if _devtools != nil {
+ f.devtools = _devtools.(bool)
+ }
- mainWindow := NewWindow(f.frontendOptions, f.debug)
+ mainWindow := NewWindow(f.frontendOptions, f.debug, f.devtools)
f.mainWindow = mainWindow
f.mainWindow.Center()
diff --git a/v2/internal/frontend/desktop/darwin/main.m b/v2/internal/frontend/desktop/darwin/main.m
index d2f39bccb..45a7d2684 100644
--- a/v2/internal/frontend/desktop/darwin/main.m
+++ b/v2/internal/frontend/desktop/darwin/main.m
@@ -215,10 +215,11 @@ int main(int argc, const char * argv[]) {
int hideWindowOnClose = 0;
const char* appearance = "NSAppearanceNameDarkAqua";
int windowIsTranslucent = 1;
- int debug = 1;
+ int devtools = 1;
+ int defaultContextMenu = 1;
int windowStartState = 0;
int startsHidden = 0;
- WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState,
+ WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtools, defaultContextMenu, windowStartState,
startsHidden, 400, 400, 600, 600, false);
SetBackgroundColour(result, 255, 0, 0, 255);
void *m = NewMenu("");
diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go
index 8b4c77799..c4fb9c0f3 100644
--- a/v2/internal/frontend/desktop/darwin/window.go
+++ b/v2/internal/frontend/desktop/darwin/window.go
@@ -40,7 +40,7 @@ func bool2Cint(value bool) C.int {
return C.int(0)
}
-func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
+func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window {
c := NewCalloc()
defer c.Free()
@@ -51,7 +51,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
startsHidden := bool2Cint(frontendOptions.StartHidden)
- debug := bool2Cint(debugMode)
+ devtoolsEnabled := bool2Cint(devtools)
+ defaultContextMenu := bool2Cint(frontendOptions.EnableDefaultContextMenu)
var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int
var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
@@ -86,8 +87,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
}
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
- alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden,
- minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings)
+ alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenu,
+ windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings)
// Create menu
result := &Window{
@@ -114,7 +115,7 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
result.SetApplicationMenu(frontendOptions.Menu)
}
- if debugMode && frontendOptions.Debug.OpenInspectorOnStartup {
+ if debug && frontendOptions.Debug.OpenInspectorOnStartup {
showInspector(result.context)
}
return result
diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go
index 58b8d746b..2f6f286fa 100644
--- a/v2/internal/frontend/desktop/linux/frontend.go
+++ b/v2/internal/frontend/desktop/linux/frontend.go
@@ -106,6 +106,7 @@ type Frontend struct {
frontendOptions *options.App
logger *logger.Logger
debug bool
+ devtools bool
// Assets
assets *assetserver.AssetServer
@@ -176,13 +177,25 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
go result.startMessageProcessor()
var _debug = ctx.Value("debug")
+ var _devtools = ctx.Value("devtools")
+
if _debug != nil {
result.debug = _debug.(bool)
}
- result.mainWindow = NewWindow(appoptions, result.debug)
+ if _devtools != nil {
+ result.devtools = _devtools.(bool)
+ }
+
+ result.mainWindow = NewWindow(appoptions, result.debug, result.devtools)
C.install_signal_handlers()
+ if appoptions.Linux != nil && appoptions.Linux.ProgramName != "" {
+ prgname := C.CString(appoptions.Linux.ProgramName)
+ C.g_set_prgname(prgname)
+ C.free(unsafe.Pointer(prgname))
+ }
+
return result
}
diff --git a/v2/internal/frontend/desktop/linux/window.go b/v2/internal/frontend/desktop/linux/window.go
index 9cc86afbb..dd087f57e 100644
--- a/v2/internal/frontend/desktop/linux/window.go
+++ b/v2/internal/frontend/desktop/linux/window.go
@@ -37,6 +37,7 @@ func gtkBool(input bool) C.gboolean {
type Window struct {
appoptions *options.App
debug bool
+ devtools bool
gtkWindow unsafe.Pointer
contentManager unsafe.Pointer
webview unsafe.Pointer
@@ -54,12 +55,13 @@ func bool2Cint(value bool) C.int {
return C.int(0)
}
-func NewWindow(appoptions *options.App, debug bool) *Window {
+func NewWindow(appoptions *options.App, debug bool, devtools bool) *Window {
validateWebKit2Version(appoptions)
result := &Window{
appoptions: appoptions,
debug: debug,
+ devtools: devtools,
minHeight: appoptions.MinHeight,
minWidth: appoptions.MinWidth,
maxHeight: appoptions.MaxHeight,
@@ -95,9 +97,9 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
defer C.free(unsafe.Pointer(buttonPressedName))
C.ConnectButtons(unsafe.Pointer(webview))
- if debug {
- C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(appoptions.Debug.OpenInspectorOnStartup))
- } else {
+ if devtools {
+ C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(debug && appoptions.Debug.OpenInspectorOnStartup))
+ } else if !appoptions.EnableDefaultContextMenu {
C.DisableContextMenu(unsafe.Pointer(webview))
}
diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go
index 82289e054..76cecbc93 100644
--- a/v2/internal/frontend/desktop/windows/frontend.go
+++ b/v2/internal/frontend/desktop/windows/frontend.go
@@ -21,9 +21,9 @@ import (
"time"
"github.com/bep/debounce"
+ "github.com/wailsapp/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
@@ -48,6 +48,7 @@ type Frontend struct {
logger *logger.Logger
chromium *edge.Chromium
debug bool
+ devtools bool
// Assets
assets *assetserver.AssetServer
@@ -142,9 +143,14 @@ func (f *Frontend) Run(ctx context.Context) error {
f.mainWindow = mainWindow
var _debug = ctx.Value("debug")
+ var _devtools = ctx.Value("devtools")
+
if _debug != nil {
f.debug = _debug.(bool)
}
+ if _devtools != nil {
+ f.devtools = _devtools.(bool)
+ }
f.WindowCenter()
f.setupChromium()
@@ -489,11 +495,11 @@ func (f *Frontend) setupChromium() {
if err != nil {
log.Fatal(err)
}
- err = settings.PutAreDefaultContextMenusEnabled(f.debug)
+ err = settings.PutAreDefaultContextMenusEnabled(f.devtools || f.frontendOptions.EnableDefaultContextMenu)
if err != nil {
log.Fatal(err)
}
- err = settings.PutAreDevToolsEnabled(f.debug)
+ err = settings.PutAreDevToolsEnabled(f.devtools)
if err != nil {
log.Fatal(err)
}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/LICENSE b/v2/internal/frontend/desktop/windows/go-webview2/LICENSE
deleted file mode 100644
index ef2a0f485..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-MIT License
-
-Copyright (c) 2020 John Chadwick
-Some portions Copyright (c) 2017 Serge Zaitsev
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/README.md b/v2/internal/frontend/desktop/windows/go-webview2/README.md
deleted file mode 100644
index 7379b3025..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# go-webview2
-
-This is a proof of concept for embedding Webview2 into Go without CGo. It is based
-on [webview/webview](https://github.com/webview/webview) and provides a compatible API.
-
-## Notice
-
-Because this version doesn't currently have an EdgeHTML fallback, it will not work unless you have a Webview2 runtime
-installed. In addition, it requires the Webview2Loader DLL in order to function. Adding an EdgeHTML fallback should be
-technically possible but will likely require much worse hacks since the API is not strictly COM to my knowledge.
-
-## Demo
-
-For now, you'll need to install the Webview2 runtime, as it does not ship with Windows.
-
-[WebView2 runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)
-
-After that, you should be able to run go-webview2 directly:
-
-```
-go run go-webview2/cmd/demo
-```
-
-This will use go-winloader to load an embedded copy of WebView2Loader.dll.
-
-If this does not work, please try running from a directory that has an appropriate copy of `WebView2Loader.dll` for your
-GOARCH. If _that_ worked, *please* file a bug so we can figure out what's wrong with go-winloader :)
\ No newline at end of file
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go b/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go
deleted file mode 100644
index 2b564173f..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/internal/w32/w32.go
+++ /dev/null
@@ -1,157 +0,0 @@
-//go:build windows
-
-package w32
-
-import (
- "syscall"
- "unicode/utf16"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- ole32 = windows.NewLazySystemDLL("ole32")
- Ole32CoInitializeEx = ole32.NewProc("CoInitializeEx")
-
- kernel32 = windows.NewLazySystemDLL("kernel32")
- Kernel32GetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId")
-
- shlwapi = windows.NewLazySystemDLL("shlwapi")
- shlwapiSHCreateMemStream = shlwapi.NewProc("SHCreateMemStream")
-
- user32 = windows.NewLazySystemDLL("user32")
- User32LoadImageW = user32.NewProc("LoadImageW")
- User32GetSystemMetrics = user32.NewProc("GetSystemMetrics")
- User32RegisterClassExW = user32.NewProc("RegisterClassExW")
- User32CreateWindowExW = user32.NewProc("CreateWindowExW")
- User32DestroyWindow = user32.NewProc("DestroyWindow")
- User32ShowWindow = user32.NewProc("ShowWindow")
- User32UpdateWindow = user32.NewProc("UpdateWindow")
- User32SetFocus = user32.NewProc("SetFocus")
- User32GetMessageW = user32.NewProc("GetMessageW")
- User32TranslateMessage = user32.NewProc("TranslateMessage")
- User32DispatchMessageW = user32.NewProc("DispatchMessageW")
- User32DefWindowProcW = user32.NewProc("DefWindowProcW")
- User32GetClientRect = user32.NewProc("GetClientRect")
- User32PostQuitMessage = user32.NewProc("PostQuitMessage")
- User32SetWindowTextW = user32.NewProc("SetWindowTextW")
- User32PostThreadMessageW = user32.NewProc("PostThreadMessageW")
- User32GetWindowLongPtrW = user32.NewProc("GetWindowLongPtrW")
- User32SetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW")
- User32AdjustWindowRect = user32.NewProc("AdjustWindowRect")
- User32SetWindowPos = user32.NewProc("SetWindowPos")
-)
-
-const (
- SystemMetricsCxIcon = 11
- SystemMetricsCyIcon = 12
-)
-
-const (
- SWShow = 5
-)
-
-const (
- SWPNoZOrder = 0x0004
- SWPNoActivate = 0x0010
- SWPNoMove = 0x0002
- SWPFrameChanged = 0x0020
-)
-
-const (
- WMDestroy = 0x0002
- WMMove = 0x0003
- WMSize = 0x0005
- WMClose = 0x0010
- WMQuit = 0x0012
- WMGetMinMaxInfo = 0x0024
- WMNCLButtonDown = 0x00A1
- WMMoving = 0x0216
- WMApp = 0x8000
-)
-
-const (
- GWLStyle = -16
-)
-
-const (
- WSOverlapped = 0x00000000
- WSMaximizeBox = 0x00020000
- WSThickFrame = 0x00040000
- WSCaption = 0x00C00000
- WSSysMenu = 0x00080000
- WSMinimizeBox = 0x00020000
- WSOverlappedWindow = (WSOverlapped | WSCaption | WSSysMenu | WSThickFrame | WSMinimizeBox | WSMaximizeBox)
-)
-
-type WndClassExW struct {
- CbSize uint32
- Style uint32
- LpfnWndProc uintptr
- CnClsExtra int32
- CbWndExtra int32
- HInstance windows.Handle
- HIcon windows.Handle
- HCursor windows.Handle
- HbrBackground windows.Handle
- LpszMenuName *uint16
- LpszClassName *uint16
- HIconSm windows.Handle
-}
-
-type Rect struct {
- Left int32
- Top int32
- Right int32
- Bottom int32
-}
-
-type MinMaxInfo struct {
- PtReserved Point
- PtMaxSize Point
- PtMaxPosition Point
- PtMinTrackSize Point
- PtMaxTrackSize Point
-}
-
-type Point struct {
- X, Y int32
-}
-
-type Msg struct {
- Hwnd syscall.Handle
- Message uint32
- WParam uintptr
- LParam uintptr
- Time uint32
- Pt Point
- LPrivate uint32
-}
-
-func Utf16PtrToString(p *uint16) string {
- if p == nil {
- return ""
- }
- // Find NUL terminator.
- end := unsafe.Pointer(p)
- n := 0
- for *(*uint16)(end) != 0 {
- end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
- n++
- }
- s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
- return string(utf16.Decode(s))
-}
-
-func SHCreateMemStream(data []byte) (uintptr, error) {
- ret, _, err := shlwapiSHCreateMemStream.Call(
- uintptr(unsafe.Pointer(&data[0])),
- uintptr(len(data)),
- )
- if ret == 0 {
- return 0, err
- }
-
- return ret, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/bridge.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/bridge.go
deleted file mode 100644
index ccf04243f..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/bridge.go
+++ /dev/null
@@ -1,239 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "fmt"
- "runtime"
- "sync"
- "sync/atomic"
-)
-
-var (
- comIfcePointersL sync.RWMutex
- comIfcePointers = map[uintptr]*comObject{} // Map from ComInterfacePointer to the Go ComObject
-)
-
-// Resolve the GoInterface of the specified ComInterfacePointer
-func Resolve[T IUnknown](ifceP uintptr) T {
- comIfcePointersL.RLock()
- comObj := comIfcePointers[ifceP]
- comIfcePointersL.RUnlock()
-
- var n T
- if comObj != nil {
- t := comObj.resolve(ifceP)
- if t != nil {
- n = t.(T)
- }
- }
-
- return n
-}
-
-// New returns a new ComObject which implements the specified Com Interface, com calls will be redirected
-// to the specified go interface.
-func New[T IUnknown](obj T) *ComObject[T] {
- cObj := new(
- ifceDef[T]{obj},
- )
- return newComObject[T](cObj)
-}
-
-// New2 returns a new ComObject which implements the two specified Com Interfaces, com calls will be redirected
-// to those interfaces accordingly.
-// This is needed if a ComObject should implement two interfaces that are not descendants of each other,
-// then you get multiple inheritance.
-func New2[T IUnknown, T2 IUnknown](obj T, obj2 T2) *ComObject[T] {
- cObj := new(
- ifceDef[T]{obj},
- ifceDef[T2]{obj2},
- )
- return newComObject[T](cObj)
-}
-
-// new returns a new ComObject which implements multiple specified Com Interfaces, com calls will be redirected
-// to the specified go interfaces accordingly.
-// This is needed if a ComObject should implement multiple interfaces that are not descendants of each other,
-// then you get multiple inheritance.
-func new(impls ...ifceImpl) *comObject {
- impls = append([]ifceImpl{ifceDef[IUnknown]{}}, impls...)
-
- cObj := &comObject{
- refCount: 1,
- ifces: map[string]int{},
- ifcesImpl: make([]comInterfaceDesc, len(impls)),
- }
-
- for i, ifceDef := range impls {
- vtable, err := ifceDef.ifce()
- if err != nil {
- panic(err)
- }
-
- needsImplement := false
- for table := vtable; table != nil; table = table.Parent {
- guid := table.ComGUID
- if i, found := cObj.ifces[guid]; found {
- // This Interface is already implemented
- if guid == iUnknownGUID {
- // IUnknown is a special interface and never has an user specific implementation
- } else if cObj.ifcesImpl[i].impl != ifceDef.impl() {
- panic(fmt.Sprintf("Interface '%s' is already implemented by another object", table.Name))
- }
-
- break
- }
-
- needsImplement = true
- cObj.ifces[guid] = i
- }
-
- if !needsImplement {
- continue
- }
-
- ifceP, ifcePSlice := allocUintptrObject(1)
- ifcePSlice[0] = vtable.ComVTable
- cObj.ifcesImpl[i] = comInterfaceDesc{ifceP, ifceDef.impl()}
- }
-
- comIfcePointersL.Lock()
- for _, ifceImpl := range cObj.ifcesImpl {
- comIfcePointers[ifceImpl.ref] = cObj
- }
- comIfcePointersL.Unlock()
-
- return cObj
-}
-
-func newComObject[T IUnknown](comObj *comObject) *ComObject[T] {
- c := &ComObject[T]{obj: comObj}
- // Make sure to async release since release needs locks and might block the finalizer goroutine for a longer period
- runtime.SetFinalizer(c, func(obj *ComObject[T]) { obj.close(true) })
- return c
-}
-
-// ComObject describes an exported go instance to be used as a ComObject which implements
-// the specified Interface.
-type ComObject[T IUnknown] struct {
- obj *comObject
- closed int32
-}
-
-// Ref returns the native uintptr that points to the ComObject that is an interface pointer to T.
-// This can be used in native calls. If the object has been closed this function will panic.
-func (o *ComObject[T]) Ref() uintptr {
- if atomic.LoadInt32(&o.closed) != 0 {
- panic("ComObject has been released")
- }
- return o.obj.queryInterface(guidOf[T](), false)
-}
-
-// Close releases the native com object from the go side. It will only be destroyed if the ref counter
-// reaches zero.
-// After closing `Ref()` will panic.
-func (o *ComObject[T]) Close() error {
- o.close(false)
- return nil
-}
-
-// close releases the native com object from the go side. It will only be destroyed if the ref counter
-// reaches zero.
-// After closing `Ref()` will panic.
-func (o *ComObject[T]) close(asyncRelease bool) {
- if atomic.CompareAndSwapInt32(&o.closed, 0, 1) {
- runtime.SetFinalizer(o, nil)
- if asyncRelease {
- go o.obj.release()
- } else {
- o.obj.release()
- }
- }
-}
-
-type comInterfaceDesc struct {
- ref uintptr // The native Com InterfacePointer
- impl any // The golang target object
-}
-
-type comObject struct {
- l sync.Mutex
-
- refCount int32
- ifces map[string]int // Map of ComInterfaceGUID to Interface Slots
- ifcesImpl []comInterfaceDesc // Slots with InterfaceDescriptors
-}
-
-func (c *comObject) queryInterface(ifceGUID string, withAddRef bool) uintptr {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on released com object")
- }
-
- i, found := c.ifces[ifceGUID]
- if !found {
- return 0
- }
-
- if withAddRef {
- c.refCount++
- }
- return c.ifcesImpl[i].ref
-}
-
-func (c *comObject) resolve(ifceP uintptr) any {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on destroyed com object")
- }
-
- for _, ifce := range c.ifcesImpl {
- if ifce.ref != ifceP {
- continue
- }
-
- return ifce.impl
- }
- return nil
-}
-
-func (c *comObject) addRef() int32 {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on destroyed com object")
- }
-
- c.refCount++
- return c.refCount
-}
-
-func (c *comObject) release() int32 {
- c.l.Lock()
- defer c.l.Unlock()
- if c.refCount <= 0 {
- panic("call on destroyed com object")
- }
-
- if c.refCount--; c.refCount == 0 {
- comIfcePointersL.Lock()
- for _, ref := range c.ifcesImpl {
- delete(comIfcePointers, ref.ref)
- }
- comIfcePointersL.Unlock()
-
- for _, impl := range c.ifcesImpl {
- ref := impl.ref
- if ref == 0 {
- continue
- }
-
- globalFree(ref)
- }
- }
-
- return c.refCount
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown.go
deleted file mode 100644
index 90d7247fe..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown.go
+++ /dev/null
@@ -1,56 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "golang.org/x/sys/windows"
-)
-
-const iUnknownGUID = "{00000000-0000-0000-C000-000000000046}"
-
-func init() {
- registerVTableInternal[IUnknown, IUnknown](
- iUnknownGUID,
- true,
- iUnknownQueryInterface,
- iUnknownAddRef,
- iUnknownRelease,
- )
-}
-
-type IUnknown interface{}
-
-func iUnknownQueryInterface(this uintptr, refiid *windows.GUID, ppvObject *uintptr) uintptr {
- if refiid == nil || ppvObject == nil {
- return uintptr(windows.E_INVALIDARG)
- }
-
- comIfcePointersL.RLock()
- obj := comIfcePointers[this]
- comIfcePointersL.RUnlock()
-
- ref := obj.queryInterface(refiid.String(), true)
- if ref != 0 {
- *ppvObject = ref
- return windows.NO_ERROR
- }
-
- *ppvObject = 0
- return uintptr(windows.E_NOINTERFACE)
-}
-
-func iUnknownAddRef(this uintptr) uintptr {
- comIfcePointersL.RLock()
- obj := comIfcePointers[this]
- comIfcePointersL.RUnlock()
-
- return uintptr(obj.addRef())
-}
-
-func iUnknownRelease(this uintptr) uintptr {
- comIfcePointersL.RLock()
- obj := comIfcePointers[this]
- comIfcePointersL.RUnlock()
-
- return uintptr(obj.release())
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown_impl.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown_impl.go
deleted file mode 100644
index 4c748d461..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/iunknown_impl.go
+++ /dev/null
@@ -1,74 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-// IUnknownFromPointer cast a generic pointer into a IUnknownImpl pointer
-func IUnknownFromPointer(ref unsafe.Pointer) *IUnknownImpl {
- return (*IUnknownImpl)(ref)
-}
-
-// IUnknownFromPointer cast native pointer into a IUnknownImpl pointer
-func IUnknownFromUintptr(ref uintptr) *IUnknownImpl {
- return IUnknownFromPointer(unsafe.Pointer(ref))
-}
-
-type IUnknownVtbl struct {
- queryInterface uintptr
- addRef uintptr
- release uintptr
-}
-
-func (i *IUnknownVtbl) QueryInterface(this unsafe.Pointer, refiid *windows.GUID, ppvObject **IUnknownImpl) error {
- r, _, _ := syscall.SyscallN(
- i.queryInterface,
- uintptr(this),
- uintptr(unsafe.Pointer(refiid)),
- uintptr(unsafe.Pointer(ppvObject)),
- )
-
- if r != uintptr(windows.S_OK) {
- return syscall.Errno(r)
- }
-
- return nil
-}
-
-func (i *IUnknownVtbl) AddRef(this unsafe.Pointer) uint32 {
- r, _, _ := syscall.SyscallN(
- i.addRef,
- uintptr(this),
- )
- return uint32(r)
-}
-
-func (i *IUnknownVtbl) Release(this unsafe.Pointer) uint32 {
- r, _, _ := syscall.SyscallN(
- i.release,
- uintptr(this),
- )
-
- return uint32(r)
-}
-
-type IUnknownImpl struct {
- vtbl *IUnknownVtbl
-}
-
-func (i *IUnknownImpl) QueryInterface(refiid *windows.GUID, ppvObject **IUnknownImpl) error {
- return i.vtbl.QueryInterface(unsafe.Pointer(i), refiid, ppvObject)
-}
-
-func (i *IUnknownImpl) AddRef() uint32 {
- return i.vtbl.AddRef(unsafe.Pointer(i))
-}
-
-func (i *IUnknownImpl) Release() uint32 {
- return i.vtbl.Release(unsafe.Pointer(i))
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/syscall.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/syscall.go
deleted file mode 100644
index 17b7f500e..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/syscall.go
+++ /dev/null
@@ -1,39 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
- procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
- procGlobalFree = modkernel32.NewProc("GlobalFree")
-
- uintptrSize = unsafe.Sizeof(uintptr(0))
-)
-
-func allocUintptrObject(size int) (uintptr, []uintptr) {
- v := globalAlloc(uintptr(size) * uintptrSize)
- slice := unsafe.Slice((*uintptr)(unsafe.Pointer(v)), size)
- return v, slice
-}
-
-func globalAlloc(dwBytes uintptr) uintptr {
- ret, _, _ := procGlobalAlloc.Call(uintptr(0), dwBytes)
- if ret == 0 {
- panic("globalAlloc failed")
- }
-
- return ret
-}
-
-func globalFree(data uintptr) {
- ret, _, _ := procGlobalFree.Call(data)
- if ret != 0 {
- panic("globalFree failed")
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/vtables.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/vtables.go
deleted file mode 100644
index b099a7848..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge/vtables.go
+++ /dev/null
@@ -1,147 +0,0 @@
-//go:build windows
-
-package combridge
-
-import (
- "fmt"
- "reflect"
- "sync"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- vTablesL sync.Mutex
- vTables = make(map[string]*vTable)
-)
-
-// RegisterVTable registers the vtable trampoline methods for the specified ComInterface
-// TBase is the base interface of T, and must be another ComInterface which roots in IUnknown or IUnknown itself.
-// The first paramter of the fn is always the uintptr of the ComObject and the GoObject can be resolved with Resolve().
-// After having resolved the GoObject the call must be redirected to the GoObject.
-// Typically a trampoline FN looks like this.
-//
-// func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this uintptr, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
-// return combridge.Resolve[_ICoreWebView2NavigationCompletedEventHandler](this).NavigationCompleted(sender, args)
-// }
-//
-// The order of registration must be in the correct order as specified in the IDL of the interface.
-func RegisterVTable[TParent, T IUnknown](guid string, fns ...interface{}) {
- registerVTableInternal[TParent, T](guid, false, fns...)
-}
-
-type vTable struct {
- Parent *vTable
-
- Name string
- ComGUID string
- ComVTable uintptr
- ComProcs []uintptr
-}
-
-func registerVTableInternal[TParent, T IUnknown](guid string, isInternal bool, fns ...interface{}) {
- vTablesL.Lock()
- defer vTablesL.Unlock()
-
- t, tName := typeInterfaceToString[T]()
- tParent, tParentName := typeInterfaceToString[TParent]()
- if !t.Implements(tParent) {
- panic(fmt.Errorf("RegisterVTable '%s': '%s' must implement '%s'", tName, tName, tParentName))
- }
-
- if !isInternal {
- if t == reflect.TypeOf((*IUnknown)(nil)).Elem() {
- panic(fmt.Errorf("RegisterVTable '%s' IUnknown can't be registered", tName))
- }
-
- if t == tParent {
- panic(fmt.Errorf("RegisterVTable '%s': T and TParent can't be the same type", tName))
- }
- }
-
- var parent *vTable
- var parentProcs []uintptr
- var parentProcsCount int
- if t != tParent {
- parent = vTables[tParentName]
- if parent == nil {
- panic(fmt.Errorf("RegisterVTable '%s': Parent VTable '%s' not registered", tName, tParentName))
- }
-
- parentProcs = parent.ComProcs
- parentProcsCount = len(parentProcs)
- }
-
- comGuid, err := windows.GUIDFromString(guid)
- if err != nil {
- panic(fmt.Errorf("RegisterVTable '%s': invalid guid: %s", tName, err))
- }
-
- vTable := &vTable{
- Parent: parent,
- Name: tName,
- ComGUID: comGuid.String(),
- }
- vTable.ComVTable, vTable.ComProcs = allocUintptrObject(parentProcsCount + len(fns))
-
- for i, proc := range parentProcs {
- vTable.ComProcs[i] = proc
- }
-
- for i, fn := range fns {
- vTable.ComProcs[parentProcsCount+i] = windows.NewCallback(fn)
- }
-
- vTables[tName] = vTable
-}
-
-func typeInterfaceToString[T any]() (reflect.Type, string) {
- t := reflect.TypeOf((*T)(nil))
- if t.Kind() != reflect.Pointer {
- panic("must be a (*yourInterfaceType)(nil)")
- }
- t = t.Elem()
- return t, t.PkgPath() + "/" + t.Name()
-}
-
-func typeInterfaceToStringOnly[T any]() string {
- _, nane := typeInterfaceToString[T]()
- return nane
-}
-
-func guidOf[T any]() string {
- vtable := vTableOf[T]()
- if vtable == nil {
- return ""
- }
- return vtable.ComGUID
-}
-
-func vTableOf[T any]() *vTable {
- name := typeInterfaceToStringOnly[T]()
- vTablesL.Lock()
- defer vTablesL.Unlock()
-
- return vTables[name]
-}
-
-type ifceImpl interface {
- impl() any
- ifce() (*vTable, error)
-}
-
-type ifceDef[T any] struct {
- objImpl any
-}
-
-func (i ifceDef[T]) impl() any {
- return i.objImpl
-}
-
-func (i ifceDef[T]) ifce() (*vTable, error) {
- vtable := vTableOf[T]()
- if vtable == nil {
- return nil, fmt.Errorf("Unable to find vTable for %s", typeInterfaceToStringOnly[T]())
- }
- return vtable, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go
deleted file mode 100644
index 429ecef24..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_COLOR.go
+++ /dev/null
@@ -1,10 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_COLOR struct {
- A uint8
- R uint8
- G uint8
- B uint8
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go
deleted file mode 100644
index ed106ed44..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND uint32
-
-const (
- COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY = iota
- COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW
- COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go
deleted file mode 100644
index 607147535..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_KEY_EVENT_KIND.go
+++ /dev/null
@@ -1,12 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_KEY_EVENT_KIND uint32
-
-const (
- COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN = 0
- COREWEBVIEW2_KEY_EVENT_KIND_KEY_UP = 1
- COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN = 2
- COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_UP = 3
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go
deleted file mode 100644
index c1679cc37..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_MOVE_FOCUS_REASON.go
+++ /dev/null
@@ -1,11 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_MOVE_FOCUS_REASON uint32
-
-const (
- COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC = 0
- COREWEBVIEW2_MOVE_FOCUS_REASON_NEXT = 1
- COREWEBVIEW2_MOVE_FOCUS_REASON_PREVIOUS = 2
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go
deleted file mode 100644
index dd8834255..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PHYSICAL_KEY_STATUS.go
+++ /dev/null
@@ -1,12 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_PHYSICAL_KEY_STATUS struct {
- RepeatCount uint32
- ScanCode uint32
- IsExtendedKey bool
- IsMenuKeyDown bool
- WasKeyDown bool
- IsKeyReleased bool
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PROCESS_FAILED_KIND.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PROCESS_FAILED_KIND.go
deleted file mode 100644
index a7e9aa339..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_PROCESS_FAILED_KIND.go
+++ /dev/null
@@ -1,49 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_PROCESS_FAILED_KIND uint32
-
-const (
- // Indicates that the browser process ended unexpectedly. The WebView
- // automatically moves to the Closed state. The app has to recreate a new
- // WebView to recover from this failure.
- COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED = 0
-
- // Indicates that the main frame's render process ended unexpectedly. A new
- // render process is created automatically and navigated to an error page.
- // You can use the `Reload` method to try to reload the page that failed.
- COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED = 1
-
- // Indicates that the main frame's render process is unresponsive.
- //
- // Note that this does not seem to work right now.
- // Does not fire for simple long running script case, the only related test
- // SitePerProcessBrowserTest::NoCommitTimeoutForInvisibleWebContents is
- // disabled.
- COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE = 2
-
- // Indicates that a frame-only render process ended unexpectedly. The process
- // exit does not affect the top-level document, only a subset of the
- // subframes within it. The content in these frames is replaced with an error
- // page in the frame.
- COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED = 3
-
- // Indicates that a utility process ended unexpectedly.
- COREWEBVIEW2_PROCESS_FAILED_KIND_UTILITY_PROCESS_EXITED = 4
-
- // Indicates that a sandbox helper process ended unexpectedly.
- COREWEBVIEW2_PROCESS_FAILED_KIND_SANDBOX_HELPER_PROCESS_EXITED = 5
-
- // Indicates that the GPU process ended unexpectedly.
- COREWEBVIEW2_PROCESS_FAILED_KIND_GPU_PROCESS_EXITED = 6
-
- // Indicates that a PPAPI plugin process ended unexpectedly.
- COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_PLUGIN_PROCESS_EXITED = 7
-
- // Indicates that a PPAPI plugin broker process ended unexpectedly.
- COREWEBVIEW2_PROCESS_FAILED_KIND_PPAPI_BROKER_PROCESS_EXITED = 8
-
- // Indicates that a process of unspecified kind ended unexpectedly.
- COREWEBVIEW2_PROCESS_FAILED_KIND_UNKNOWN_PROCESS_EXITED = 9
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go
deleted file mode 100644
index 2e9261d0e..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/COREWEBVIEW2_WEB_RESOURCE_CONTEXT.go
+++ /dev/null
@@ -1,25 +0,0 @@
-//go:build windows
-
-package edge
-
-type COREWEBVIEW2_WEB_RESOURCE_CONTEXT uint32
-
-const (
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL = 0
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_DOCUMENT = 1
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_STYLESHEET = 2
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_IMAGE = 3
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MEDIA = 4
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FONT = 5
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SCRIPT = 6
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_XML_HTTP_REQUEST = 7
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_FETCH = 8
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_TEXT_TRACK = 9
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_EVENT_SOURCE = 10
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_WEBSOCKET = 11
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_MANIFEST = 12
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_SIGNED_EXCHANGE = 13
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_PING = 14
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_CSP_VIOLATION_REPORT = 15
- COREWEBVIEW2_WEB_RESOURCE_CONTEXT_OTHER = 16
-)
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go
deleted file mode 100644
index 2a3a9c823..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventArgs.go
+++ /dev/null
@@ -1,79 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2AcceleratorKeyPressedEventArgsVtbl struct {
- _IUnknownVtbl
- GetKeyEventKind ComProc
- GetVirtualKey ComProc
- GetKeyEventLParam ComProc
- GetPhysicalKeyStatus ComProc
- GetHandled ComProc
- PutHandled ComProc
-}
-
-type ICoreWebView2AcceleratorKeyPressedEventArgs struct {
- vtbl *_ICoreWebView2AcceleratorKeyPressedEventArgsVtbl
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetKeyEventKind() (COREWEBVIEW2_KEY_EVENT_KIND, error) {
- var err error
- var keyEventKind COREWEBVIEW2_KEY_EVENT_KIND
- _, _, err = i.vtbl.GetKeyEventKind.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&keyEventKind)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
- return keyEventKind, nil
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetVirtualKey() (uint, error) {
- var err error
- var virtualKey uint
- _, _, err = i.vtbl.GetVirtualKey.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&virtualKey)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
- return virtualKey, nil
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) GetPhysicalKeyStatus() (COREWEBVIEW2_PHYSICAL_KEY_STATUS, error) {
- var err error
- var physicalKeyStatus COREWEBVIEW2_PHYSICAL_KEY_STATUS
- _, _, err = i.vtbl.GetPhysicalKeyStatus.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&physicalKeyStatus)),
- )
- if err != windows.ERROR_SUCCESS {
- return COREWEBVIEW2_PHYSICAL_KEY_STATUS{}, err
- }
- return physicalKeyStatus, nil
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventArgs) PutHandled(handled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutHandled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(handled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go
deleted file mode 100644
index 2c276560b..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2AcceleratorKeyPressedEventHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type ICoreWebView2AcceleratorKeyPressedEventHandler struct {
- vtbl *_ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl
- impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl
-}
-
-func (i *ICoreWebView2AcceleratorKeyPressedEventHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface(this *ICoreWebView2AcceleratorKeyPressedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease(this *ICoreWebView2AcceleratorKeyPressedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke(this *ICoreWebView2AcceleratorKeyPressedEventHandler, sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
- return this.impl.AcceleratorKeyPressed(sender, args)
-}
-
-type _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl interface {
- _IUnknownImpl
- AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr
-}
-
-var _ICoreWebView2AcceleratorKeyPressedEventHandlerFn = _ICoreWebView2AcceleratorKeyPressedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2AcceleratorKeyPressedEventHandlerInvoke),
-}
-
-func newICoreWebView2AcceleratorKeyPressedEventHandler(impl _ICoreWebView2AcceleratorKeyPressedEventHandlerImpl) *ICoreWebView2AcceleratorKeyPressedEventHandler {
- return &ICoreWebView2AcceleratorKeyPressedEventHandler{
- vtbl: &_ICoreWebView2AcceleratorKeyPressedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go
deleted file mode 100644
index c95a00ade..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller.go
+++ /dev/null
@@ -1,160 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "math"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2ControllerVtbl struct {
- _IUnknownVtbl
- GetIsVisible ComProc
- PutIsVisible ComProc
- GetBounds ComProc
- PutBounds ComProc
- GetZoomFactor ComProc
- PutZoomFactor ComProc
- AddZoomFactorChanged ComProc
- RemoveZoomFactorChanged ComProc
- SetBoundsAndZoomFactor ComProc
- MoveFocus ComProc
- AddMoveFocusRequested ComProc
- RemoveMoveFocusRequested ComProc
- AddGotFocus ComProc
- RemoveGotFocus ComProc
- AddLostFocus ComProc
- RemoveLostFocus ComProc
- AddAcceleratorKeyPressed ComProc
- RemoveAcceleratorKeyPressed ComProc
- GetParentWindow ComProc
- PutParentWindow ComProc
- NotifyParentWindowPositionChanged ComProc
- Close ComProc
- GetCoreWebView2 ComProc
-}
-
-type ICoreWebView2Controller struct {
- vtbl *_ICoreWebView2ControllerVtbl
-}
-
-func (i *ICoreWebView2Controller) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2Controller) GetBounds() (*w32.Rect, error) {
- var err error
- var bounds w32.Rect
- _, _, err = i.vtbl.GetBounds.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&bounds)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return &bounds, nil
-}
-
-func (i *ICoreWebView2Controller) PutBounds(bounds w32.Rect) error {
- var err error
-
- _, _, err = i.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&bounds)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) MoveFocus(reason COREWEBVIEW2_MOVE_FOCUS_REASON) error {
- var err error
-
- _, _, err = i.vtbl.MoveFocus.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(reason),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) AddAcceleratorKeyPressed(eventHandler *ICoreWebView2AcceleratorKeyPressedEventHandler, token *_EventRegistrationToken) error {
- var err error
- _, _, err = i.vtbl.AddAcceleratorKeyPressed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(eventHandler)),
- uintptr(unsafe.Pointer(&token)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) PutIsVisible(isVisible bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsVisible.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isVisible)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) GetICoreWebView2Controller2() *ICoreWebView2Controller2 {
-
- var result *ICoreWebView2Controller2
-
- iidICoreWebView2Controller2 := NewGUID("{c979903e-d4ca-4228-92eb-47ee3fa96eab}")
- i.vtbl.QueryInterface.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(iidICoreWebView2Controller2)),
- uintptr(unsafe.Pointer(&result)))
-
- return result
-}
-
-func (i *ICoreWebView2Controller) NotifyParentWindowPositionChanged() error {
- var err error
- _, _, err = i.vtbl.NotifyParentWindowPositionChanged.Call(
- uintptr(unsafe.Pointer(i)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) PutZoomFactor(zoomFactor float64) error {
- var err error
- _, _, err = i.vtbl.PutZoomFactor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(math.Float64bits(zoomFactor)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Controller) GetZoomFactor() (float64, error) {
- var err error
- var zoomFactorUint64 uint64
- _, _, err = i.vtbl.GetZoomFactor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&zoomFactorUint64)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0.0, err
- }
- return math.Float64frombits(zoomFactorUint64), nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go
deleted file mode 100644
index eff315a91..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Controller2.go
+++ /dev/null
@@ -1,75 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2Controller2Vtbl struct {
- _IUnknownVtbl
- GetIsVisible ComProc
- PutIsVisible ComProc
- GetBounds ComProc
- PutBounds ComProc
- GetZoomFactor ComProc
- PutZoomFactor ComProc
- AddZoomFactorChanged ComProc
- RemoveZoomFactorChanged ComProc
- SetBoundsAndZoomFactor ComProc
- MoveFocus ComProc
- AddMoveFocusRequested ComProc
- RemoveMoveFocusRequested ComProc
- AddGotFocus ComProc
- RemoveGotFocus ComProc
- AddLostFocus ComProc
- RemoveLostFocus ComProc
- AddAcceleratorKeyPressed ComProc
- RemoveAcceleratorKeyPressed ComProc
- GetParentWindow ComProc
- PutParentWindow ComProc
- NotifyParentWindowPositionChanged ComProc
- Close ComProc
- GetCoreWebView2 ComProc
- GetDefaultBackgroundColor ComProc
- PutDefaultBackgroundColor ComProc
-}
-
-type ICoreWebView2Controller2 struct {
- vtbl *_ICoreWebView2Controller2Vtbl
-}
-
-func (i *ICoreWebView2Controller2) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2Controller2) GetDefaultBackgroundColor() (*COREWEBVIEW2_COLOR, error) {
- var err error
- var backgroundColor *COREWEBVIEW2_COLOR
- _, _, err = i.vtbl.GetDefaultBackgroundColor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&backgroundColor)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return backgroundColor, nil
-}
-
-func (i *ICoreWebView2Controller2) PutDefaultBackgroundColor(backgroundColor COREWEBVIEW2_COLOR) error {
- var err error
-
- // Cast to a uint32 as that's what the call is expecting
- col := *(*uint32)(unsafe.Pointer(&backgroundColor))
-
- _, _, err = i.vtbl.PutDefaultBackgroundColor.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(col),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go
deleted file mode 100644
index c0e4d13b7..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2CreateCoreWebView2ControllerCompletedHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2CreateCoreWebView2ControllerCompletedHandler struct {
- vtbl *_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl
- impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl
-}
-
-func (i *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler, errorCode uintptr, createdController *ICoreWebView2Controller) uintptr {
- return this.impl.CreateCoreWebView2ControllerCompleted(errorCode, createdController)
-}
-
-type _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl interface {
- _IUnknownImpl
- CreateCoreWebView2ControllerCompleted(errorCode uintptr, createdController *ICoreWebView2Controller) uintptr
-}
-
-var _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn = _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerInvoke),
-}
-
-func newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(impl _ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler {
- return &iCoreWebView2CreateCoreWebView2ControllerCompletedHandler{
- vtbl: &_ICoreWebView2CreateCoreWebView2ControllerCompletedHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpHeadersCollectionIterator.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpHeadersCollectionIterator.go
deleted file mode 100644
index 0c9eacb46..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpHeadersCollectionIterator.go
+++ /dev/null
@@ -1,78 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2HttpHeadersCollectionIteratorVtbl struct {
- _IUnknownVtbl
- GetCurrentHeader ComProc
- GetHasCurrentHeader ComProc
- MoveNext ComProc
-}
-
-type ICoreWebView2HttpHeadersCollectionIterator struct {
- vtbl *_ICoreWebView2HttpHeadersCollectionIteratorVtbl
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) HasCurrentHeader() (bool, error) {
- var hasHeader int32
- res, _, err := i.vtbl.GetHasCurrentHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&hasHeader)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- if windows.Handle(res) != windows.S_OK {
- return false, syscall.Errno(res)
- }
- return hasHeader != 0, nil
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) GetCurrentHeader() (string, string, error) {
- // Create *uint16 to hold result
- var _name *uint16
- var _value *uint16
- res, _, err := i.vtbl.GetCurrentHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&_name)),
- uintptr(unsafe.Pointer(&_value)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", "", err
- }
- if windows.Handle(res) != windows.S_OK {
- return "", "", syscall.Errno(res)
- }
- // Get result and cleanup
- name := windows.UTF16PtrToString(_name)
- windows.CoTaskMemFree(unsafe.Pointer(_name))
- value := windows.UTF16PtrToString(_value)
- windows.CoTaskMemFree(unsafe.Pointer(_value))
- return name, value, nil
-}
-
-func (i *ICoreWebView2HttpHeadersCollectionIterator) MoveNext() (bool, error) {
- var next int32
- res, _, err := i.vtbl.MoveNext.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&next)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- if windows.Handle(res) != windows.S_OK {
- return false, syscall.Errno(res)
- }
- return next != 0, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpRequestHeaders.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpRequestHeaders.go
deleted file mode 100644
index 5a147b299..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2HttpRequestHeaders.go
+++ /dev/null
@@ -1,101 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-const (
- ERROR_ELEMENT_NOT_FOUND syscall.Errno = 0x80070490
-)
-
-type _ICoreWebView2HttpRequestHeadersVtbl struct {
- _IUnknownVtbl
- GetHeader ComProc
- GetHeaders ComProc
- Contains ComProc
- SetHeader ComProc
- RemoveHeader ComProc
- GetIterator ComProc
-}
-
-type ICoreWebView2HttpRequestHeaders struct {
- vtbl *_ICoreWebView2HttpRequestHeadersVtbl
-}
-
-func (i *ICoreWebView2HttpRequestHeaders) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
-
-// GetHeader returns the value of the specified header. If the header is not found
-// ERROR_ELEMENT_NOT_FOUND is returned as error.
-func (i *ICoreWebView2HttpRequestHeaders) GetHeader(name string) (string, error) {
- _name, err := windows.UTF16PtrFromString(name)
- if err != nil {
- return "", nil
- }
-
- var _value *uint16
- res, _, err := i.vtbl.GetHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_name)),
- uintptr(unsafe.Pointer(&_value)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- }
- if windows.Handle(res) != windows.S_OK {
- return "", syscall.Errno(res)
- }
-
- value := windows.UTF16PtrToString(_value)
- windows.CoTaskMemFree(unsafe.Pointer(_value))
- return value, nil
-}
-
-// SetHeader sets the specified header to the value.
-func (i *ICoreWebView2HttpRequestHeaders) SetHeader(name, value string) error {
- _name, err := windows.UTF16PtrFromString(name)
- if err != nil {
- return nil
- }
-
- _value, err := windows.UTF16PtrFromString(value)
- if err != nil {
- return nil
- }
-
- res, _, err := i.vtbl.SetHeader.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_name)),
- uintptr(unsafe.Pointer(_value)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- if windows.Handle(res) != windows.S_OK {
- return syscall.Errno(res)
- }
- return nil
-}
-
-// GetIterator returns an iterator over the collection of request headers. Make sure to call
-// Release on the returned Object after finished using it.
-func (i *ICoreWebView2HttpRequestHeaders) GetIterator() (*ICoreWebView2HttpHeadersCollectionIterator, error) {
- var headers *ICoreWebView2HttpHeadersCollectionIterator
- res, _, err := i.vtbl.GetIterator.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&headers)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- if windows.Handle(res) != windows.S_OK {
- return nil, syscall.Errno(res)
- }
- return headers, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go
deleted file mode 100644
index c3998e0a2..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventArgs.go
+++ /dev/null
@@ -1,18 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2NavigationCompletedEventArgsVtbl struct {
- _IUnknownVtbl
- GetIsSuccess ComProc
- GetWebErrorStatus ComProc
- GetNavigationId ComProc
-}
-
-type ICoreWebView2NavigationCompletedEventArgs struct {
- vtbl *_ICoreWebView2NavigationCompletedEventArgsVtbl
-}
-
-func (i *ICoreWebView2NavigationCompletedEventArgs) AddRef() uintptr {
- return i.AddRef()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go
deleted file mode 100644
index 456da5074..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2NavigationCompletedEventHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2NavigationCompletedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type ICoreWebView2NavigationCompletedEventHandler struct {
- vtbl *_ICoreWebView2NavigationCompletedEventHandlerVtbl
- impl _ICoreWebView2NavigationCompletedEventHandlerImpl
-}
-
-func (i *ICoreWebView2NavigationCompletedEventHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface(this *ICoreWebView2NavigationCompletedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease(this *ICoreWebView2NavigationCompletedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2NavigationCompletedEventHandlerInvoke(this *ICoreWebView2NavigationCompletedEventHandler, sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
- return this.impl.NavigationCompleted(sender, args)
-}
-
-type _ICoreWebView2NavigationCompletedEventHandlerImpl interface {
- _IUnknownImpl
- NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr
-}
-
-var _ICoreWebView2NavigationCompletedEventHandlerFn = _ICoreWebView2NavigationCompletedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2NavigationCompletedEventHandlerInvoke),
-}
-
-func newICoreWebView2NavigationCompletedEventHandler(impl _ICoreWebView2NavigationCompletedEventHandlerImpl) *ICoreWebView2NavigationCompletedEventHandler {
- return &ICoreWebView2NavigationCompletedEventHandler{
- vtbl: &_ICoreWebView2NavigationCompletedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2ProcessFailedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2ProcessFailedEventArgs.go
deleted file mode 100644
index b6d3cda1b..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2ProcessFailedEventArgs.go
+++ /dev/null
@@ -1,41 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "fmt"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2ProcessFailedEventArgsVtbl struct {
- _IUnknownVtbl
- GetProcessFailedKind ComProc
-}
-
-type ICoreWebView2ProcessFailedEventArgs struct {
- vtbl *_ICoreWebView2ProcessFailedEventArgsVtbl
-}
-
-func (i *ICoreWebView2ProcessFailedEventArgs) GetProcessFailedKind() (COREWEBVIEW2_PROCESS_FAILED_KIND, error) {
- kind := COREWEBVIEW2_PROCESS_FAILED_KIND(0xffffffff)
- hr, _, err := i.vtbl.GetProcessFailedKind.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&kind)),
- )
-
- if windows.Handle(hr) != windows.S_OK {
- return 0, syscall.Errno(hr)
- }
-
- if kind == 0xffffffff {
- if err == nil {
- err = fmt.Errorf("unknown error")
- }
- return 0, err
- }
-
- return kind, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2ProcessFailedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2ProcessFailedEventHandler.go
deleted file mode 100644
index fc8c7369c..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2ProcessFailedEventHandler.go
+++ /dev/null
@@ -1,53 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2ProcessFailedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type ICoreWebView2ProcessFailedEventHandler struct {
- vtbl *_ICoreWebView2ProcessFailedEventHandlerVtbl
- impl _ICoreWebView2ProcessFailedEventHandlerImpl
-}
-
-func (i *ICoreWebView2ProcessFailedEventHandler) AddRef() uintptr {
- return i.AddRef()
-}
-func _ICoreWebView2ProcessFailedEventHandlerIUnknownQueryInterface(this *ICoreWebView2ProcessFailedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2ProcessFailedEventHandlerIUnknownAddRef(this *ICoreWebView2ProcessFailedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2ProcessFailedEventHandlerIUnknownRelease(this *ICoreWebView2ProcessFailedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2ProcessFailedEventHandlerInvoke(this *ICoreWebView2ProcessFailedEventHandler, sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr {
- return this.impl.ProcessFailed(sender, args)
-}
-
-type _ICoreWebView2ProcessFailedEventHandlerImpl interface {
- _IUnknownImpl
- ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr
-}
-
-var _ICoreWebView2ProcessFailedEventHandlerFn = _ICoreWebView2ProcessFailedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2ProcessFailedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2ProcessFailedEventHandlerInvoke),
-}
-
-func newICoreWebView2ProcessFailedEventHandler(impl _ICoreWebView2ProcessFailedEventHandlerImpl) *ICoreWebView2ProcessFailedEventHandler {
- return &ICoreWebView2ProcessFailedEventHandler{
- vtbl: &_ICoreWebView2ProcessFailedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go
deleted file mode 100644
index a4ba613d2..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2Settings.go
+++ /dev/null
@@ -1,271 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2SettingsVtbl struct {
- _IUnknownVtbl
- GetIsScriptEnabled ComProc
- PutIsScriptEnabled ComProc
- GetIsWebMessageEnabled ComProc
- PutIsWebMessageEnabled ComProc
- GetAreDefaultScriptDialogsEnabled ComProc
- PutAreDefaultScriptDialogsEnabled ComProc
- GetIsStatusBarEnabled ComProc
- PutIsStatusBarEnabled ComProc
- GetAreDevToolsEnabled ComProc
- PutAreDevToolsEnabled ComProc
- GetAreDefaultContextMenusEnabled ComProc
- PutAreDefaultContextMenusEnabled ComProc
- GetAreHostObjectsAllowed ComProc
- PutAreHostObjectsAllowed ComProc
- GetIsZoomControlEnabled ComProc
- PutIsZoomControlEnabled ComProc
- GetIsBuiltInErrorPageEnabled ComProc
- PutIsBuiltInErrorPageEnabled ComProc
-}
-
-type ICoreWebView2Settings struct {
- vtbl *_ICoreWebView2SettingsVtbl
-}
-
-func (i *ICoreWebView2Settings) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2Settings) GetIsScriptEnabled() (bool, error) {
- var err error
- var isScriptEnabled bool
- _, _, err = i.vtbl.GetIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isScriptEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsScriptEnabled(isScriptEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsWebMessageEnabled() (bool, error) {
- var err error
- var isWebMessageEnabled bool
- _, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isWebMessageEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
- var err error
- var areDefaultScriptDialogsEnabled bool
- _, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDefaultScriptDialogsEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsStatusBarEnabled() (bool, error) {
- var err error
- var isStatusBarEnabled bool
- _, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isStatusBarEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreDevToolsEnabled() (bool, error) {
- var err error
- var areDevToolsEnabled bool
- _, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDevToolsEnabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreDefaultContextMenusEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreDefaultContextMenusEnabled(enabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetAreHostObjectsAllowed() (bool, error) {
- var err error
- var allowed bool
- _, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return allowed, nil
-}
-
-func (i *ICoreWebView2Settings) PutAreHostObjectsAllowed(allowed bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsZoomControlEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsZoomControlEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2Settings) GetIsBuiltInErrorPageEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebView2Settings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go
deleted file mode 100644
index fe7f2cfa2..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequest.go
+++ /dev/null
@@ -1,102 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2WebResourceRequestVtbl struct {
- _IUnknownVtbl
- GetUri ComProc
- PutUri ComProc
- GetMethod ComProc
- PutMethod ComProc
- GetContent ComProc
- PutContent ComProc
- GetHeaders ComProc
-}
-
-type ICoreWebView2WebResourceRequest struct {
- vtbl *_ICoreWebView2WebResourceRequestVtbl
-}
-
-func (i *ICoreWebView2WebResourceRequest) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2WebResourceRequest) GetMethod() (string, error) {
- // Create *uint16 to hold result
- var _method *uint16
- res, _, err := i.vtbl.GetMethod.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&_method)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- }
- if windows.Handle(res) != windows.S_OK {
- return "", syscall.Errno(res)
- }
- // Get result and cleanup
- uri := windows.UTF16PtrToString(_method)
- windows.CoTaskMemFree(unsafe.Pointer(_method))
- return uri, nil
-}
-
-func (i *ICoreWebView2WebResourceRequest) GetUri() (string, error) {
- var err error
- // Create *uint16 to hold result
- var _uri *uint16
- _, _, err = i.vtbl.GetUri.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&_uri)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- } // Get result and cleanup
- uri := windows.UTF16PtrToString(_uri)
- windows.CoTaskMemFree(unsafe.Pointer(_uri))
- return uri, nil
-}
-
-// GetContent returns the body of the request. Returns nil if there's no body. Make sure to call
-// Release on the returned IStream after finished using it.
-func (i *ICoreWebView2WebResourceRequest) GetContent() (*IStream, error) {
- var stream *IStream
- res, _, err := i.vtbl.GetContent.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&stream)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- if windows.Handle(res) != windows.S_OK {
- return nil, syscall.Errno(res)
- }
- return stream, nil
-}
-
-// GetHeaders returns the mutable HTTP request headers. Make sure to call
-// Release on the returned Object after finished using it.
-func (i *ICoreWebView2WebResourceRequest) GetHeaders() (*ICoreWebView2HttpRequestHeaders, error) {
- var headers *ICoreWebView2HttpRequestHeaders
- res, _, err := i.vtbl.GetHeaders.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&headers)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- if windows.Handle(res) != windows.S_OK {
- return nil, syscall.Errno(res)
- }
- return headers, nil
-}
-
-func (i *ICoreWebView2WebResourceRequest) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go
deleted file mode 100644
index 614594e87..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventArgs.go
+++ /dev/null
@@ -1,52 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _ICoreWebView2WebResourceRequestedEventArgsVtbl struct {
- _IUnknownVtbl
- GetRequest ComProc
- GetResponse ComProc
- PutResponse ComProc
- GetDeferral ComProc
- GetResourceContext ComProc
-}
-
-type ICoreWebView2WebResourceRequestedEventArgs struct {
- vtbl *_ICoreWebView2WebResourceRequestedEventArgsVtbl
-}
-
-func (i *ICoreWebView2WebResourceRequestedEventArgs) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2WebResourceRequestedEventArgs) PutResponse(response *ICoreWebView2WebResourceResponse) error {
- var err error
-
- _, _, err = i.vtbl.PutResponse.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(response)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2WebResourceRequestedEventArgs) GetRequest() (*ICoreWebView2WebResourceRequest, error) {
- var err error
- var request *ICoreWebView2WebResourceRequest
- _, _, err = i.vtbl.GetRequest.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&request)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return request, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go
deleted file mode 100644
index d0860c3be..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceRequestedEventHandler.go
+++ /dev/null
@@ -1,50 +0,0 @@
-//go:build windows
-
-package edge
-
-type _ICoreWebView2WebResourceRequestedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2WebResourceRequestedEventHandler struct {
- vtbl *_ICoreWebView2WebResourceRequestedEventHandlerVtbl
- impl _ICoreWebView2WebResourceRequestedEventHandlerImpl
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebResourceRequestedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease(this *iCoreWebView2WebResourceRequestedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2WebResourceRequestedEventHandlerInvoke(this *iCoreWebView2WebResourceRequestedEventHandler, sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
- return this.impl.WebResourceRequested(sender, args)
-}
-
-type _ICoreWebView2WebResourceRequestedEventHandlerImpl interface {
- _IUnknownImpl
- WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr
-}
-
-var _ICoreWebView2WebResourceRequestedEventHandlerFn = _ICoreWebView2WebResourceRequestedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2WebResourceRequestedEventHandlerInvoke),
-}
-
-func newICoreWebView2WebResourceRequestedEventHandler(impl _ICoreWebView2WebResourceRequestedEventHandlerImpl) *iCoreWebView2WebResourceRequestedEventHandler {
- return &iCoreWebView2WebResourceRequestedEventHandler{
- vtbl: &_ICoreWebView2WebResourceRequestedEventHandlerFn,
- impl: impl,
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go
deleted file mode 100644
index dd02e6089..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2WebResourceResponse.go
+++ /dev/null
@@ -1,28 +0,0 @@
-//go:build windows
-
-package edge
-
-import "unsafe"
-
-type _ICoreWebView2WebResourceResponseVtbl struct {
- _IUnknownVtbl
- GetContent ComProc
- PutContent ComProc
- GetHeaders ComProc
- GetStatusCode ComProc
- PutStatusCode ComProc
- GetReasonPhrase ComProc
- PutReasonPhrase ComProc
-}
-
-type ICoreWebView2WebResourceResponse struct {
- vtbl *_ICoreWebView2WebResourceResponseVtbl
-}
-
-func (i *ICoreWebView2WebResourceResponse) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebView2WebResourceResponse) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go
deleted file mode 100644
index 85a4f71fa..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_2.go
+++ /dev/null
@@ -1,18 +0,0 @@
-//go:build windows
-
-package edge
-
-type iCoreWebView2_2Vtbl struct {
- iCoreWebView2Vtbl
- AddWebResourceResponseReceived ComProc
- RemoveWebResourceResponseReceived ComProc
- NavigateWithWebResourceRequest ComProc
- AddDomContentLoaded ComProc
- RemoveDomContentLoaded ComProc
- GetCookieManager ComProc
- GetEnvironment ComProc
-}
-
-type ICoreWebView2_2 struct {
- vtbl *iCoreWebView2_2Vtbl
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go
deleted file mode 100644
index 58424bd6a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebView2_3.go
+++ /dev/null
@@ -1,62 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type iCoreWebView2_3Vtbl struct {
- iCoreWebView2_2Vtbl
- TrySuspend ComProc
- Resume ComProc
- GetIsSuspended ComProc
- SetVirtualHostNameToFolderMapping ComProc
- ClearVirtualHostNameToFolderMapping ComProc
-}
-
-type ICoreWebView2_3 struct {
- vtbl *iCoreWebView2_3Vtbl
-}
-
-func (i *ICoreWebView2_3) SetVirtualHostNameToFolderMapping(hostName, folderPath string, accessKind COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND) error {
- _hostName, err := windows.UTF16PtrFromString(hostName)
- if err != nil {
- return err
- }
-
- _folderPath, err := windows.UTF16PtrFromString(folderPath)
- if err != nil {
- return err
- }
-
- _, _, err = i.vtbl.SetVirtualHostNameToFolderMapping.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_hostName)),
- uintptr(unsafe.Pointer(_folderPath)),
- uintptr(accessKind),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
-
- return nil
-}
-
-func (i *ICoreWebView2) GetICoreWebView2_3() *ICoreWebView2_3 {
- var result *ICoreWebView2_3
-
- iidICoreWebView2_3 := NewGUID("{A0D6DF20-3B92-416D-AA0C-437A9C727857}")
- _, _, _ = i.vtbl.QueryInterface.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(iidICoreWebView2_3)),
- uintptr(unsafe.Pointer(&result)))
-
- return result
-}
-
-func (e *Chromium) GetICoreWebView2_3() *ICoreWebView2_3 {
- return e.webview.GetICoreWebView2_3()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
deleted file mode 100644
index 6c6b16d74..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
+++ /dev/null
@@ -1,397 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-// ICoreWebviewSettings is the merged settings class
-
-type _ICoreWebViewSettingsVtbl struct {
- _IUnknownVtbl
- GetIsScriptEnabled ComProc
- PutIsScriptEnabled ComProc
- GetIsWebMessageEnabled ComProc
- PutIsWebMessageEnabled ComProc
- GetAreDefaultScriptDialogsEnabled ComProc
- PutAreDefaultScriptDialogsEnabled ComProc
- GetIsStatusBarEnabled ComProc
- PutIsStatusBarEnabled ComProc
- GetAreDevToolsEnabled ComProc
- PutAreDevToolsEnabled ComProc
- GetAreDefaultContextMenusEnabled ComProc
- PutAreDefaultContextMenusEnabled ComProc
- GetAreHostObjectsAllowed ComProc
- PutAreHostObjectsAllowed ComProc
- GetIsZoomControlEnabled ComProc
- PutIsZoomControlEnabled ComProc
- GetIsBuiltInErrorPageEnabled ComProc
- PutIsBuiltInErrorPageEnabled ComProc
- GetUserAgent ComProc // ICoreWebView2Settings2: SDK 1.0.864.35
- PutUserAgent ComProc
- GetAreBrowserAcceleratorKeysEnabled ComProc // ICoreWebView2Settings3: SDK 1.0.864.35
- PutAreBrowserAcceleratorKeysEnabled ComProc
- GetIsPasswordAutosaveEnabled ComProc // ICoreWebView2Settings4: SDK 1.0.902.49
- PutIsPasswordAutosaveEnabled ComProc
- GetIsGeneralAutofillEnabled ComProc
- PutIsGeneralAutofillEnabled ComProc
- GetIsPinchZoomEnabled ComProc // ICoreWebView2Settings5: SDK 1.0.902.49
- PutIsPinchZoomEnabled ComProc
- GetIsSwipeNavigationEnabled ComProc // ICoreWebView2Settings6: SDK 1.0.992.28
- PutIsSwipeNavigationEnabled ComProc
-}
-
-type ICoreWebViewSettings struct {
- vtbl *_ICoreWebViewSettingsVtbl
-}
-
-func (i *ICoreWebViewSettings) AddRef() uintptr {
- return i.AddRef()
-}
-
-func (i *ICoreWebViewSettings) GetIsScriptEnabled() (bool, error) {
- var err error
- var isScriptEnabled bool
- _, _, err = i.vtbl.GetIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isScriptEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsScriptEnabled(isScriptEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsScriptEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isScriptEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsWebMessageEnabled() (bool, error) {
- var err error
- var isWebMessageEnabled bool
- _, _, err = i.vtbl.GetIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isWebMessageEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsWebMessageEnabled(isWebMessageEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsWebMessageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isWebMessageEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreDefaultScriptDialogsEnabled() (bool, error) {
- var err error
- var areDefaultScriptDialogsEnabled bool
- _, _, err = i.vtbl.GetAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDefaultScriptDialogsEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreDefaultScriptDialogsEnabled(areDefaultScriptDialogsEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreDefaultScriptDialogsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDefaultScriptDialogsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsStatusBarEnabled() (bool, error) {
- var err error
- var isStatusBarEnabled bool
- _, _, err = i.vtbl.GetIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return isStatusBarEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsStatusBarEnabled(isStatusBarEnabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsStatusBarEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(isStatusBarEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreDevToolsEnabled() (bool, error) {
- var err error
- var areDevToolsEnabled bool
- _, _, err = i.vtbl.GetAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return areDevToolsEnabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreDevToolsEnabled(areDevToolsEnabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDevToolsEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(areDevToolsEnabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreDefaultContextMenusEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreDefaultContextMenusEnabled(enabled bool) error {
- var err error
- _, _, err = i.vtbl.PutAreDefaultContextMenusEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreHostObjectsAllowed() (bool, error) {
- var err error
- var allowed bool
- _, _, err = i.vtbl.GetAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return allowed, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreHostObjectsAllowed(allowed bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreHostObjectsAllowed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(allowed)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsZoomControlEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsZoomControlEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsZoomControlEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsBuiltInErrorPageEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsBuiltInErrorPageEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsBuiltInErrorPageEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetUserAgent() (string, error) {
- var err error
- // Create *uint16 to hold result
- var _userAgent *uint16
- _, _, err = i.vtbl.GetUserAgent.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_userAgent)),
- )
- if err != windows.ERROR_SUCCESS {
- return "", err
- } // Get result and cleanup
- userAgent := windows.UTF16PtrToString(_userAgent)
- windows.CoTaskMemFree(unsafe.Pointer(_userAgent))
- return userAgent, nil
-}
-
-func (i *ICoreWebViewSettings) PutUserAgent(userAgent string) error {
- var err error
- // Convert string 'userAgent' to *uint16
- _userAgent, err := windows.UTF16PtrFromString(userAgent)
- if err != nil {
- return err
- }
-
- _, _, err = i.vtbl.PutUserAgent.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_userAgent)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetAreBrowserAcceleratorKeysEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetAreBrowserAcceleratorKeysEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutAreBrowserAcceleratorKeysEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutAreBrowserAcceleratorKeysEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsPinchZoomEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsPinchZoomEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsPinchZoomEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsPinchZoomEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebViewSettings) GetIsSwipeNavigationEnabled() (bool, error) {
- var err error
- var enabled bool
- _, _, err = i.vtbl.GetIsSwipeNavigationEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return false, err
- }
- return enabled, nil
-}
-
-func (i *ICoreWebViewSettings) PutIsSwipeNavigationEnabled(enabled bool) error {
- var err error
-
- _, _, err = i.vtbl.PutIsSwipeNavigationEnabled.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(boolToInt(enabled)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go
deleted file mode 100644
index 9e29ca4f0..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/IStream.go
+++ /dev/null
@@ -1,54 +0,0 @@
-//go:build windows
-
-package edge
-
-import (
- "io"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-type _IStreamVtbl struct {
- _IUnknownVtbl
- Read ComProc
- Write ComProc
-}
-
-type IStream struct {
- vtbl *_IStreamVtbl
-}
-
-func (i *IStream) Release() error {
- return i.vtbl.CallRelease(unsafe.Pointer(i))
-}
-
-func (i *IStream) Read(p []byte) (int, error) {
- bufLen := len(p)
- if bufLen == 0 {
- return 0, nil
- }
-
- var n int
- res, _, err := i.vtbl.Read.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&p[0])),
- uintptr(bufLen),
- uintptr(unsafe.Pointer(&n)),
- )
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
-
- switch windows.Handle(res) {
- case windows.S_OK:
- // The buffer has been completely filled
- return n, nil
- case windows.S_FALSE:
- // The buffer has been filled with less than len data and the stream is EOF
- return n, io.EOF
- default:
- return 0, syscall.Errno(res)
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
deleted file mode 100644
index 376891bb1..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
+++ /dev/null
@@ -1,419 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "errors"
- "log"
- "os"
- "path/filepath"
- "strings"
- "sync/atomic"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "golang.org/x/sys/windows"
-)
-
-type Rect = w32.Rect
-
-type Chromium struct {
- hwnd uintptr
- controller *ICoreWebView2Controller
- webview *ICoreWebView2
- inited uintptr
- envCompleted *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
- controllerCompleted *iCoreWebView2CreateCoreWebView2ControllerCompletedHandler
- webMessageReceived *iCoreWebView2WebMessageReceivedEventHandler
- permissionRequested *iCoreWebView2PermissionRequestedEventHandler
- webResourceRequested *iCoreWebView2WebResourceRequestedEventHandler
- acceleratorKeyPressed *ICoreWebView2AcceleratorKeyPressedEventHandler
- navigationCompleted *ICoreWebView2NavigationCompletedEventHandler
- processFailed *ICoreWebView2ProcessFailedEventHandler
-
- environment *ICoreWebView2Environment
-
- padding Rect
-
- // Settings
- Debug bool
- DataPath string
- BrowserPath string
- AdditionalBrowserArgs []string
-
- // permissions
- permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState
- globalPermission *CoreWebView2PermissionState
-
- // Callbacks
- MessageCallback func(string)
- WebResourceRequestedCallback func(request *ICoreWebView2WebResourceRequest, args *ICoreWebView2WebResourceRequestedEventArgs)
- NavigationCompletedCallback func(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs)
- ProcessFailedCallback func(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs)
- AcceleratorKeyCallback func(uint) bool
-}
-
-func NewChromium() *Chromium {
- e := &Chromium{}
- /*
- All these handlers are passed to native code through syscalls with 'uintptr(unsafe.Pointer(handler))' and we know
- that a pointer to those will be kept in the native code. Furthermore these handlers als contain pointer to other Go
- structs like the vtable.
- This violates the unsafe.Pointer rule '(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.' because
- theres no guarantee that Go doesn't move these objects.
- AFAIK currently the Go runtime doesn't move HEAP objects, so we should be safe with these handlers. But they don't
- guarantee it, because in the future Go might use a compacting GC.
- There's a proposal to add a runtime.Pin function, to prevent moving pinned objects, which would allow to easily fix
- this issue by just pinning the handlers. The https://go-review.googlesource.com/c/go/+/367296/ should land in Go 1.19.
- */
- e.envCompleted = newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(e)
- e.controllerCompleted = newICoreWebView2CreateCoreWebView2ControllerCompletedHandler(e)
- e.webMessageReceived = newICoreWebView2WebMessageReceivedEventHandler(e)
- e.permissionRequested = newICoreWebView2PermissionRequestedEventHandler(e)
- e.webResourceRequested = newICoreWebView2WebResourceRequestedEventHandler(e)
- e.acceleratorKeyPressed = newICoreWebView2AcceleratorKeyPressedEventHandler(e)
- e.navigationCompleted = newICoreWebView2NavigationCompletedEventHandler(e)
- e.processFailed = newICoreWebView2ProcessFailedEventHandler(e)
- e.permissions = make(map[CoreWebView2PermissionKind]CoreWebView2PermissionState)
-
- return e
-}
-
-func (e *Chromium) Embed(hwnd uintptr) bool {
- e.hwnd = hwnd
-
- dataPath := e.DataPath
- if dataPath == "" {
- currentExePath := make([]uint16, windows.MAX_PATH)
- _, err := windows.GetModuleFileName(windows.Handle(0), ¤tExePath[0], windows.MAX_PATH)
- if err != nil {
- // What to do here?
- return false
- }
- currentExeName := filepath.Base(windows.UTF16ToString(currentExePath))
- dataPath = filepath.Join(os.Getenv("AppData"), currentExeName)
- }
-
- if e.BrowserPath != "" {
- if _, err := os.Stat(e.BrowserPath); errors.Is(err, os.ErrNotExist) {
- log.Printf("Browser path %s does not exist", e.BrowserPath)
- return false
- }
- }
-
- browserArgs := strings.Join(e.AdditionalBrowserArgs, " ")
- if err := createCoreWebView2EnvironmentWithOptions(e.BrowserPath, dataPath, e.envCompleted, browserArgs); err != nil {
- log.Printf("Error calling Webview2Loader: %v", err)
- return false
- }
-
- var msg w32.Msg
- for {
- if atomic.LoadUintptr(&e.inited) != 0 {
- break
- }
- r, _, _ := w32.User32GetMessageW.Call(
- uintptr(unsafe.Pointer(&msg)),
- 0,
- 0,
- 0,
- )
- if r == 0 {
- break
- }
- w32.User32TranslateMessage.Call(uintptr(unsafe.Pointer(&msg)))
- w32.User32DispatchMessageW.Call(uintptr(unsafe.Pointer(&msg)))
- }
- e.Init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}")
- return true
-}
-
-func (e *Chromium) SetPadding(padding Rect) {
- if e.padding.Top == padding.Top && e.padding.Bottom == padding.Bottom &&
- e.padding.Left == padding.Left && e.padding.Right == padding.Right {
-
- return
- }
-
- e.padding = padding
- e.Resize()
-}
-
-func (e *Chromium) Resize() {
- if e.hwnd == 0 {
- return
- }
-
- var bounds w32.Rect
- w32.User32GetClientRect.Call(e.hwnd, uintptr(unsafe.Pointer(&bounds)))
-
- bounds.Top += e.padding.Top
- bounds.Bottom -= e.padding.Bottom
- bounds.Left += e.padding.Left
- bounds.Right -= e.padding.Right
-
- e.SetSize(bounds)
-}
-
-func (e *Chromium) Navigate(url string) {
- e.webview.vtbl.Navigate.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(url))),
- )
-}
-
-func (e *Chromium) Init(script string) {
- e.webview.vtbl.AddScriptToExecuteOnDocumentCreated.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(script))),
- 0,
- )
-}
-
-func (e *Chromium) Eval(script string) {
-
- _script, err := windows.UTF16PtrFromString(script)
- if err != nil {
- log.Fatal(err)
- }
-
- e.webview.vtbl.ExecuteScript.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(_script)),
- 0,
- )
-}
-
-func (e *Chromium) Show() error {
- return e.controller.PutIsVisible(true)
-}
-
-func (e *Chromium) Hide() error {
- return e.controller.PutIsVisible(false)
-}
-
-func (e *Chromium) QueryInterface(_, _ uintptr) uintptr {
- return 0
-}
-
-func (e *Chromium) AddRef() uintptr {
- return 1
-}
-
-func (e *Chromium) Release() uintptr {
- return 1
-}
-
-func (e *Chromium) EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr {
- if int32(res) < 0 {
- log.Fatalf("Creating environment failed with %08x: %s", res, syscall.Errno(res))
- }
- env.vtbl.AddRef.Call(uintptr(unsafe.Pointer(env)))
- e.environment = env
-
- env.vtbl.CreateCoreWebView2Controller.Call(
- uintptr(unsafe.Pointer(env)),
- e.hwnd,
- uintptr(unsafe.Pointer(e.controllerCompleted)),
- )
- return 0
-}
-
-func (e *Chromium) CreateCoreWebView2ControllerCompleted(res uintptr, controller *ICoreWebView2Controller) uintptr {
- if int32(res) < 0 {
- log.Fatalf("Creating controller failed with %08x: %s", res, syscall.Errno(res))
- }
- controller.vtbl.AddRef.Call(uintptr(unsafe.Pointer(controller)))
- e.controller = controller
-
- var token _EventRegistrationToken
- controller.vtbl.GetCoreWebView2.Call(
- uintptr(unsafe.Pointer(controller)),
- uintptr(unsafe.Pointer(&e.webview)),
- )
- e.webview.vtbl.AddRef.Call(
- uintptr(unsafe.Pointer(e.webview)),
- )
- e.webview.vtbl.AddWebMessageReceived.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.webMessageReceived)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddPermissionRequested.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.permissionRequested)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddWebResourceRequested.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.webResourceRequested)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddNavigationCompleted.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.navigationCompleted)),
- uintptr(unsafe.Pointer(&token)),
- )
- e.webview.vtbl.AddProcessFailed.Call(
- uintptr(unsafe.Pointer(e.webview)),
- uintptr(unsafe.Pointer(e.processFailed)),
- uintptr(unsafe.Pointer(&token)),
- )
-
- e.controller.AddAcceleratorKeyPressed(e.acceleratorKeyPressed, &token)
-
- atomic.StoreUintptr(&e.inited, 1)
-
- return 0
-}
-
-func (e *Chromium) MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
- var message *uint16
- args.vtbl.TryGetWebMessageAsString.Call(
- uintptr(unsafe.Pointer(args)),
- uintptr(unsafe.Pointer(&message)),
- )
- if e.MessageCallback != nil {
- e.MessageCallback(w32.Utf16PtrToString(message))
- }
- sender.vtbl.PostWebMessageAsString.Call(
- uintptr(unsafe.Pointer(sender)),
- uintptr(unsafe.Pointer(message)),
- )
- windows.CoTaskMemFree(unsafe.Pointer(message))
- return 0
-}
-
-func (e *Chromium) SetPermission(kind CoreWebView2PermissionKind, state CoreWebView2PermissionState) {
- e.permissions[kind] = state
-}
-
-func (e *Chromium) SetGlobalPermission(state CoreWebView2PermissionState) {
- e.globalPermission = &state
-}
-
-func (e *Chromium) PermissionRequested(_ *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
- var kind CoreWebView2PermissionKind
- args.vtbl.GetPermissionKind.Call(
- uintptr(unsafe.Pointer(args)),
- uintptr(kind),
- )
- var result CoreWebView2PermissionState
- if e.globalPermission != nil {
- result = *e.globalPermission
- } else {
- var ok bool
- result, ok = e.permissions[kind]
- if !ok {
- result = CoreWebView2PermissionStateDefault
- }
- }
- args.vtbl.PutState.Call(
- uintptr(unsafe.Pointer(args)),
- uintptr(result),
- )
- return 0
-}
-
-func (e *Chromium) WebResourceRequested(sender *ICoreWebView2, args *ICoreWebView2WebResourceRequestedEventArgs) uintptr {
- req, err := args.GetRequest()
- if err != nil {
- log.Fatal(err)
- }
- defer req.Release()
-
- if e.WebResourceRequestedCallback != nil {
- e.WebResourceRequestedCallback(req, args)
- }
- return 0
-}
-
-func (e *Chromium) AddWebResourceRequestedFilter(filter string, ctx COREWEBVIEW2_WEB_RESOURCE_CONTEXT) {
- err := e.webview.AddWebResourceRequestedFilter(filter, ctx)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (e *Chromium) Environment() *ICoreWebView2Environment {
- return e.environment
-}
-
-// AcceleratorKeyPressed is called when an accelerator key is pressed.
-// If the AcceleratorKeyCallback method has been set, it will defer handling of the keypress
-// to the callback. That callback returns a bool indicating if the event was handled.
-func (e *Chromium) AcceleratorKeyPressed(sender *ICoreWebView2Controller, args *ICoreWebView2AcceleratorKeyPressedEventArgs) uintptr {
- if e.AcceleratorKeyCallback == nil {
- return 0
- }
- eventKind, _ := args.GetKeyEventKind()
- if eventKind == COREWEBVIEW2_KEY_EVENT_KIND_KEY_DOWN ||
- eventKind == COREWEBVIEW2_KEY_EVENT_KIND_SYSTEM_KEY_DOWN {
- virtualKey, _ := args.GetVirtualKey()
- status, _ := args.GetPhysicalKeyStatus()
- if !status.WasKeyDown {
- args.PutHandled(e.AcceleratorKeyCallback(virtualKey))
- return 0
- }
- }
- args.PutHandled(false)
- return 0
-}
-
-func (e *Chromium) GetSettings() (*ICoreWebViewSettings, error) {
- return e.webview.GetSettings()
-}
-
-func (e *Chromium) GetController() *ICoreWebView2Controller {
- return e.controller
-}
-
-func boolToInt(input bool) int {
- if input {
- return 1
- }
- return 0
-}
-
-func (e *Chromium) NavigationCompleted(sender *ICoreWebView2, args *ICoreWebView2NavigationCompletedEventArgs) uintptr {
- if e.NavigationCompletedCallback != nil {
- e.NavigationCompletedCallback(sender, args)
- }
- return 0
-}
-
-func (e *Chromium) ProcessFailed(sender *ICoreWebView2, args *ICoreWebView2ProcessFailedEventArgs) uintptr {
- if e.ProcessFailedCallback != nil {
- e.ProcessFailedCallback(sender, args)
- }
- return 0
-}
-
-func (e *Chromium) NotifyParentWindowPositionChanged() error {
- //It looks like the wndproc function is called before the controller initialization is complete.
- //Because of this the controller is nil
- if e.controller == nil {
- return nil
- }
- return e.controller.NotifyParentWindowPositionChanged()
-}
-
-func (e *Chromium) Focus() {
- err := e.controller.MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (e *Chromium) PutZoomFactor(zoomFactor float64) {
- err := e.controller.PutZoomFactor(zoomFactor)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func (e *Chromium) OpenDevToolsWindow() {
- e.webview.OpenDevToolsWindow()
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go
deleted file mode 100644
index 00f6f42fb..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_386.go
+++ /dev/null
@@ -1,23 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "unsafe"
-)
-
-func (e *Chromium) SetSize(bounds w32.Rect) {
- if e.controller == nil {
- return
- }
-
- e.controller.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(e.controller)),
- uintptr(bounds.Left),
- uintptr(bounds.Top),
- uintptr(bounds.Right),
- uintptr(bounds.Bottom),
- )
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go
deleted file mode 100644
index 858b93f17..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_amd64.go
+++ /dev/null
@@ -1,20 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
- "unsafe"
-)
-
-func (e *Chromium) SetSize(bounds w32.Rect) {
- if e.controller == nil {
- return
- }
-
- e.controller.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(e.controller)),
- uintptr(unsafe.Pointer(&bounds)),
- )
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go
deleted file mode 100644
index b237792e4..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium_arm64.go
+++ /dev/null
@@ -1,23 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
-)
-
-func (e *Chromium) SetSize(bounds w32.Rect) {
- if e.controller == nil {
- return
- }
-
- words := (*[2]uintptr)(unsafe.Pointer(&bounds))
- e.controller.vtbl.PutBounds.Call(
- uintptr(unsafe.Pointer(e.controller)),
- words[0],
- words[1],
- )
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go
deleted file mode 100644
index 6f1afbd87..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/corewebview2.go
+++ /dev/null
@@ -1,503 +0,0 @@
-//go:build windows
-// +build windows
-
-package edge
-
-import (
- "fmt"
- "log"
- "runtime"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/internal/w32"
-
- "golang.org/x/sys/windows"
-)
-
-func init() {
- runtime.LockOSThread()
-
- r, _, _ := w32.Ole32CoInitializeEx.Call(0, 2)
- if int(r) < 0 {
- log.Printf("Warning: CoInitializeEx call failed: E=%08x", r)
- }
-}
-
-type _EventRegistrationToken struct {
- value int64
-}
-
-type CoreWebView2PermissionKind uint32
-
-const (
- CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota
- CoreWebView2PermissionKindMicrophone
- CoreWebView2PermissionKindCamera
- CoreWebView2PermissionKindGeolocation
- CoreWebView2PermissionKindNotifications
- CoreWebView2PermissionKindOtherSensors
- CoreWebView2PermissionKindClipboardRead
-)
-
-type CoreWebView2PermissionState uint32
-
-const (
- CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota
- CoreWebView2PermissionStateAllow
- CoreWebView2PermissionStateDeny
-)
-
-// ComProc stores a COM procedure.
-type ComProc uintptr
-
-// NewComProc creates a new COM proc from a Go function.
-func NewComProc(fn interface{}) ComProc {
- return ComProc(windows.NewCallback(fn))
-}
-
-// Call calls a COM procedure.
-//
-//go:uintptrescapes
-func (p ComProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
- // The magic uintptrescapes comment is needed to prevent moving uintptr(unsafe.Pointer(p)) so calls to .Call() also
- // satisfy the unsafe.Pointer rule "(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall."
- // Otherwise it might be that pointers get moved, especially pointer onto the Go stack which might grow dynamically.
- // See https://pkg.go.dev/unsafe#Pointer and https://github.com/golang/go/issues/34474
- switch len(a) {
- case 0:
- return syscall.Syscall(uintptr(p), 0, 0, 0, 0)
- case 1:
- return syscall.Syscall(uintptr(p), 1, a[0], 0, 0)
- case 2:
- return syscall.Syscall(uintptr(p), 2, a[0], a[1], 0)
- case 3:
- return syscall.Syscall(uintptr(p), 3, a[0], a[1], a[2])
- case 4:
- return syscall.Syscall6(uintptr(p), 4, a[0], a[1], a[2], a[3], 0, 0)
- case 5:
- return syscall.Syscall6(uintptr(p), 5, a[0], a[1], a[2], a[3], a[4], 0)
- case 6:
- return syscall.Syscall6(uintptr(p), 6, a[0], a[1], a[2], a[3], a[4], a[5])
- case 7:
- return syscall.Syscall9(uintptr(p), 7, a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
- case 8:
- return syscall.Syscall9(uintptr(p), 8, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
- case 9:
- return syscall.Syscall9(uintptr(p), 9, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
- case 10:
- return syscall.Syscall12(uintptr(p), 10, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
- case 11:
- return syscall.Syscall12(uintptr(p), 11, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
- case 12:
- return syscall.Syscall12(uintptr(p), 12, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
- case 13:
- return syscall.Syscall15(uintptr(p), 13, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
- case 14:
- return syscall.Syscall15(uintptr(p), 14, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
- case 15:
- return syscall.Syscall15(uintptr(p), 15, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
- default:
- panic("too many arguments")
- }
-}
-
-// IUnknown
-
-type _IUnknownVtbl struct {
- QueryInterface ComProc
- AddRef ComProc
- Release ComProc
-}
-
-func (i *_IUnknownVtbl) CallRelease(this unsafe.Pointer) error {
- _, _, err := i.Release.Call(
- uintptr(this),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-type _IUnknownImpl interface {
- QueryInterface(refiid, object uintptr) uintptr
- AddRef() uintptr
- Release() uintptr
-}
-
-// ICoreWebView2
-
-type iCoreWebView2Vtbl struct {
- _IUnknownVtbl
- GetSettings ComProc
- GetSource ComProc
- Navigate ComProc
- NavigateToString ComProc
- AddNavigationStarting ComProc
- RemoveNavigationStarting ComProc
- AddContentLoading ComProc
- RemoveContentLoading ComProc
- AddSourceChanged ComProc
- RemoveSourceChanged ComProc
- AddHistoryChanged ComProc
- RemoveHistoryChanged ComProc
- AddNavigationCompleted ComProc
- RemoveNavigationCompleted ComProc
- AddFrameNavigationStarting ComProc
- RemoveFrameNavigationStarting ComProc
- AddFrameNavigationCompleted ComProc
- RemoveFrameNavigationCompleted ComProc
- AddScriptDialogOpening ComProc
- RemoveScriptDialogOpening ComProc
- AddPermissionRequested ComProc
- RemovePermissionRequested ComProc
- AddProcessFailed ComProc
- RemoveProcessFailed ComProc
- AddScriptToExecuteOnDocumentCreated ComProc
- RemoveScriptToExecuteOnDocumentCreated ComProc
- ExecuteScript ComProc
- CapturePreview ComProc
- Reload ComProc
- PostWebMessageAsJSON ComProc
- PostWebMessageAsString ComProc
- AddWebMessageReceived ComProc
- RemoveWebMessageReceived ComProc
- CallDevToolsProtocolMethod ComProc
- GetBrowserProcessID ComProc
- GetCanGoBack ComProc
- GetCanGoForward ComProc
- GoBack ComProc
- GoForward ComProc
- GetDevToolsProtocolEventReceiver ComProc
- Stop ComProc
- AddNewWindowRequested ComProc
- RemoveNewWindowRequested ComProc
- AddDocumentTitleChanged ComProc
- RemoveDocumentTitleChanged ComProc
- GetDocumentTitle ComProc
- AddHostObjectToScript ComProc
- RemoveHostObjectFromScript ComProc
- OpenDevToolsWindow ComProc
- AddContainsFullScreenElementChanged ComProc
- RemoveContainsFullScreenElementChanged ComProc
- GetContainsFullScreenElement ComProc
- AddWebResourceRequested ComProc
- RemoveWebResourceRequested ComProc
- AddWebResourceRequestedFilter ComProc
- RemoveWebResourceRequestedFilter ComProc
- AddWindowCloseRequested ComProc
- RemoveWindowCloseRequested ComProc
-}
-
-type ICoreWebView2 struct {
- vtbl *iCoreWebView2Vtbl
-}
-
-func (i *ICoreWebView2) GetSettings() (*ICoreWebViewSettings, error) {
- var err error
- var settings *ICoreWebViewSettings
- _, _, err = i.vtbl.GetSettings.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(&settings)),
- )
- if err != windows.ERROR_SUCCESS {
- return nil, err
- }
- return settings, nil
-}
-
-// ICoreWebView2Environment
-
-type iCoreWebView2EnvironmentVtbl struct {
- _IUnknownVtbl
- CreateCoreWebView2Controller ComProc
- CreateWebResourceResponse ComProc
- GetBrowserVersionString ComProc
- AddNewBrowserVersionAvailable ComProc
- RemoveNewBrowserVersionAvailable ComProc
-}
-
-type ICoreWebView2Environment struct {
- vtbl *iCoreWebView2EnvironmentVtbl
-}
-
-// CreateWebResourceResponse creates a new ICoreWebView2WebResourceResponse, it must be released after finishing using it.
-func (e *ICoreWebView2Environment) CreateWebResourceResponse(content []byte, statusCode int, reasonPhrase string, headers string) (*ICoreWebView2WebResourceResponse, error) {
- var err error
- var stream uintptr
-
- if len(content) > 0 {
- // Create stream for response
- stream, err = w32.SHCreateMemStream(content)
- if err != nil {
- return nil, err
- }
-
- // Release the IStream after we are finished, CreateWebResourceResponse Call will increase the reference
- // count on IStream and therefore it won't be freed until the reference count of the response is 0.
- defer (*IStream)(unsafe.Pointer(stream)).Release()
- }
-
- // Convert string 'uri' to *uint16
- _reason, err := windows.UTF16PtrFromString(reasonPhrase)
- if err != nil {
- return nil, err
- }
- // Convert string 'uri' to *uint16
- _headers, err := windows.UTF16PtrFromString(headers)
- if err != nil {
- return nil, err
- }
- var response *ICoreWebView2WebResourceResponse
- hr, _, err := e.vtbl.CreateWebResourceResponse.Call(
- uintptr(unsafe.Pointer(e)),
- stream,
- uintptr(statusCode),
- uintptr(unsafe.Pointer(_reason)),
- uintptr(unsafe.Pointer(_headers)),
- uintptr(unsafe.Pointer(&response)),
- )
- if windows.Handle(hr) != windows.S_OK {
- return nil, syscall.Errno(hr)
- }
-
- if response == nil {
- if err == nil {
- err = fmt.Errorf("unknown error")
- }
- return nil, err
- }
- return response, nil
-
-}
-
-// ICoreWebView2WebMessageReceivedEventArgs
-
-type iCoreWebView2WebMessageReceivedEventArgsVtbl struct {
- _IUnknownVtbl
- GetSource ComProc
- GetWebMessageAsJSON ComProc
- TryGetWebMessageAsString ComProc
-}
-
-type iCoreWebView2WebMessageReceivedEventArgs struct {
- vtbl *iCoreWebView2WebMessageReceivedEventArgsVtbl
-}
-
-// ICoreWebView2PermissionRequestedEventArgs
-
-type iCoreWebView2PermissionRequestedEventArgsVtbl struct {
- _IUnknownVtbl
- GetURI ComProc
- GetPermissionKind ComProc
- GetIsUserInitiated ComProc
- GetState ComProc
- PutState ComProc
- GetDeferral ComProc
-}
-
-type iCoreWebView2PermissionRequestedEventArgs struct {
- vtbl *iCoreWebView2PermissionRequestedEventArgsVtbl
-}
-
-// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl interface {
- _IUnknownImpl
- EnvironmentCompleted(res uintptr, env *ICoreWebView2Environment) uintptr
-}
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler struct {
- vtbl *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl
- impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, res uintptr, env *ICoreWebView2Environment) uintptr {
- return this.impl.EnvironmentCompleted(res, env)
-}
-
-var iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn = iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke),
-}
-
-func newICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler(impl iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerImpl) *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler {
- return &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler{
- vtbl: &iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerFn,
- impl: impl,
- }
-}
-
-// ICoreWebView2WebMessageReceivedEventHandler
-
-type iCoreWebView2WebMessageReceivedEventHandlerImpl interface {
- _IUnknownImpl
- MessageReceived(sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr
-}
-
-type iCoreWebView2WebMessageReceivedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2WebMessageReceivedEventHandler struct {
- vtbl *iCoreWebView2WebMessageReceivedEventHandlerVtbl
- impl iCoreWebView2WebMessageReceivedEventHandlerImpl
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface(this *iCoreWebView2WebMessageReceivedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease(this *iCoreWebView2WebMessageReceivedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2WebMessageReceivedEventHandlerInvoke(this *iCoreWebView2WebMessageReceivedEventHandler, sender *ICoreWebView2, args *iCoreWebView2WebMessageReceivedEventArgs) uintptr {
- return this.impl.MessageReceived(sender, args)
-}
-
-var iCoreWebView2WebMessageReceivedEventHandlerFn = iCoreWebView2WebMessageReceivedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2WebMessageReceivedEventHandlerInvoke),
-}
-
-func newICoreWebView2WebMessageReceivedEventHandler(impl iCoreWebView2WebMessageReceivedEventHandlerImpl) *iCoreWebView2WebMessageReceivedEventHandler {
- return &iCoreWebView2WebMessageReceivedEventHandler{
- vtbl: &iCoreWebView2WebMessageReceivedEventHandlerFn,
- impl: impl,
- }
-}
-
-// ICoreWebView2PermissionRequestedEventHandler
-
-type iCoreWebView2PermissionRequestedEventHandlerImpl interface {
- _IUnknownImpl
- PermissionRequested(sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr
-}
-
-type iCoreWebView2PermissionRequestedEventHandlerVtbl struct {
- _IUnknownVtbl
- Invoke ComProc
-}
-
-type iCoreWebView2PermissionRequestedEventHandler struct {
- vtbl *iCoreWebView2PermissionRequestedEventHandlerVtbl
- impl iCoreWebView2PermissionRequestedEventHandlerImpl
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface(this *iCoreWebView2PermissionRequestedEventHandler, refiid, object uintptr) uintptr {
- return this.impl.QueryInterface(refiid, object)
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
- return this.impl.AddRef()
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease(this *iCoreWebView2PermissionRequestedEventHandler) uintptr {
- return this.impl.Release()
-}
-
-func _ICoreWebView2PermissionRequestedEventHandlerInvoke(this *iCoreWebView2PermissionRequestedEventHandler, sender *ICoreWebView2, args *iCoreWebView2PermissionRequestedEventArgs) uintptr {
- return this.impl.PermissionRequested(sender, args)
-}
-
-var iCoreWebView2PermissionRequestedEventHandlerFn = iCoreWebView2PermissionRequestedEventHandlerVtbl{
- _IUnknownVtbl{
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownQueryInterface),
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownAddRef),
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerIUnknownRelease),
- },
- NewComProc(_ICoreWebView2PermissionRequestedEventHandlerInvoke),
-}
-
-func newICoreWebView2PermissionRequestedEventHandler(impl iCoreWebView2PermissionRequestedEventHandlerImpl) *iCoreWebView2PermissionRequestedEventHandler {
- return &iCoreWebView2PermissionRequestedEventHandler{
- vtbl: &iCoreWebView2PermissionRequestedEventHandlerFn,
- impl: impl,
- }
-}
-
-func (i *ICoreWebView2) AddWebResourceRequestedFilter(uri string, resourceContext COREWEBVIEW2_WEB_RESOURCE_CONTEXT) error {
- var err error
- // Convert string 'uri' to *uint16
- _uri, err := windows.UTF16PtrFromString(uri)
- if err != nil {
- return err
- }
- _, _, err = i.vtbl.AddWebResourceRequestedFilter.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(_uri)),
- uintptr(resourceContext),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-func (i *ICoreWebView2) AddNavigationCompleted(eventHandler *ICoreWebView2NavigationCompletedEventHandler, token *_EventRegistrationToken) error {
- var err error
- _, _, err = i.vtbl.AddNavigationCompleted.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(eventHandler)),
- uintptr(unsafe.Pointer(&token)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2) AddProcessFailed(eventHandler *ICoreWebView2ProcessFailedEventHandler, token *_EventRegistrationToken) error {
- var err error
- _, _, err = i.vtbl.AddProcessFailed.Call(
- uintptr(unsafe.Pointer(i)),
- uintptr(unsafe.Pointer(eventHandler)),
- uintptr(unsafe.Pointer(&token)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
-
-func (i *ICoreWebView2) OpenDevToolsWindow() error {
- var err error
- _, _, err = i.vtbl.OpenDevToolsWindow.Call(
- uintptr(unsafe.Pointer(i)),
- )
- if err != windows.ERROR_SUCCESS {
- return err
- }
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_go.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_go.go
deleted file mode 100644
index a3b7374ca..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_go.go
+++ /dev/null
@@ -1,29 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package edge
-
-import (
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
-)
-
-func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
- e := &environmentCreatedHandler{environmentCompletedHandle}
- return webviewloader.CreateCoreWebView2EnvironmentWithOptions(
- e,
- webviewloader.WithBrowserExecutableFolder(browserExecutableFolder),
- webviewloader.WithUserDataFolder(userDataFolder),
- webviewloader.WithAdditionalBrowserArguments(additionalBrowserArgs),
- )
-}
-
-type environmentCreatedHandler struct {
- originalHandler *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-}
-
-func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode webviewloader.HRESULT, createdEnvironment *webviewloader.ICoreWebView2Environment) webviewloader.HRESULT {
- env := (*ICoreWebView2Environment)(unsafe.Pointer(createdEnvironment))
- res := r.originalHandler.impl.EnvironmentCompleted(uintptr(errorCode), env)
- return webviewloader.HRESULT(res)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_native.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_native.go
deleted file mode 100644
index 9b4f02bfd..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/create_env_native.go
+++ /dev/null
@@ -1,41 +0,0 @@
-//go:build windows && native_webview2loader
-
-package edge
-
-import (
- "fmt"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
-
- "golang.org/x/sys/windows"
-)
-
-func createCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder string, environmentCompletedHandle *iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, additionalBrowserArgs string) error {
- browserPathPtr, err := windows.UTF16PtrFromString(browserExecutableFolder)
- if err != nil {
- return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", browserExecutableFolder, err)
- }
-
- userPathPtr, err := windows.UTF16PtrFromString(userDataFolder)
- if err != nil {
- return fmt.Errorf("Error calling UTF16PtrFromString for %s: %v", userDataFolder, err)
- }
-
- hr, err := webviewloader.CreateCoreWebView2EnvironmentWithOptions(
- browserPathPtr,
- userPathPtr,
- uintptr(unsafe.Pointer(environmentCompletedHandle)),
- additionalBrowserArgs,
- )
-
- if hr != 0 {
- if err == nil || err == windows.ERROR_SUCCESS {
- err = syscall.Errno(hr)
- }
- return err
- }
-
- return nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go
deleted file mode 100644
index 007e60586..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/guid.go
+++ /dev/null
@@ -1,225 +0,0 @@
-//go:build windows
-
-package edge
-
-// This code has been adapted from: https://github.com/go-ole/go-ole
-
-/*
-
-The MIT License (MIT)
-
-Copyright © 2013-2017 Yasuhiro Matsumoto,
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the “Software”), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-*/
-
-const hextable = "0123456789ABCDEF"
-const emptyGUID = "{00000000-0000-0000-0000-000000000000}"
-
-// GUID is Windows API specific GUID type.
-//
-// This exists to match Windows GUID type for direct passing for COM.
-// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.
-type GUID struct {
- Data1 uint32
- Data2 uint16
- Data3 uint16
- Data4 [8]byte
-}
-
-// NewGUID converts the given string into a globally unique identifier that is
-// compliant with the Windows API.
-//
-// The supplied string may be in any of these formats:
-//
-// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
-// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
-//
-// The conversion of the supplied string is not case-sensitive.
-func NewGUID(guid string) *GUID {
- d := []byte(guid)
- var d1, d2, d3, d4a, d4b []byte
-
- switch len(d) {
- case 38:
- if d[0] != '{' || d[37] != '}' {
- return nil
- }
- d = d[1:37]
- fallthrough
- case 36:
- if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' {
- return nil
- }
- d1 = d[0:8]
- d2 = d[9:13]
- d3 = d[14:18]
- d4a = d[19:23]
- d4b = d[24:36]
- case 32:
- d1 = d[0:8]
- d2 = d[8:12]
- d3 = d[12:16]
- d4a = d[16:20]
- d4b = d[20:32]
- default:
- return nil
- }
-
- var g GUID
- var ok1, ok2, ok3, ok4 bool
- g.Data1, ok1 = decodeHexUint32(d1)
- g.Data2, ok2 = decodeHexUint16(d2)
- g.Data3, ok3 = decodeHexUint16(d3)
- g.Data4, ok4 = decodeHexByte64(d4a, d4b)
- if ok1 && ok2 && ok3 && ok4 {
- return &g
- }
- return nil
-}
-
-func decodeHexUint32(src []byte) (value uint32, ok bool) {
- var b1, b2, b3, b4 byte
- var ok1, ok2, ok3, ok4 bool
- b1, ok1 = decodeHexByte(src[0], src[1])
- b2, ok2 = decodeHexByte(src[2], src[3])
- b3, ok3 = decodeHexByte(src[4], src[5])
- b4, ok4 = decodeHexByte(src[6], src[7])
- value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4)
- ok = ok1 && ok2 && ok3 && ok4
- return
-}
-
-func decodeHexUint16(src []byte) (value uint16, ok bool) {
- var b1, b2 byte
- var ok1, ok2 bool
- b1, ok1 = decodeHexByte(src[0], src[1])
- b2, ok2 = decodeHexByte(src[2], src[3])
- value = (uint16(b1) << 8) | uint16(b2)
- ok = ok1 && ok2
- return
-}
-
-func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) {
- var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool
- value[0], ok1 = decodeHexByte(s1[0], s1[1])
- value[1], ok2 = decodeHexByte(s1[2], s1[3])
- value[2], ok3 = decodeHexByte(s2[0], s2[1])
- value[3], ok4 = decodeHexByte(s2[2], s2[3])
- value[4], ok5 = decodeHexByte(s2[4], s2[5])
- value[5], ok6 = decodeHexByte(s2[6], s2[7])
- value[6], ok7 = decodeHexByte(s2[8], s2[9])
- value[7], ok8 = decodeHexByte(s2[10], s2[11])
- ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8
- return
-}
-
-func decodeHexByte(c1, c2 byte) (value byte, ok bool) {
- var n1, n2 byte
- var ok1, ok2 bool
- n1, ok1 = decodeHexChar(c1)
- n2, ok2 = decodeHexChar(c2)
- value = (n1 << 4) | n2
- ok = ok1 && ok2
- return
-}
-
-func decodeHexChar(c byte) (byte, bool) {
- switch {
- case '0' <= c && c <= '9':
- return c - '0', true
- case 'a' <= c && c <= 'f':
- return c - 'a' + 10, true
- case 'A' <= c && c <= 'F':
- return c - 'A' + 10, true
- }
-
- return 0, false
-}
-
-// String converts the GUID to string form. It will adhere to this pattern:
-//
-// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
-//
-// If the GUID is nil, the string representation of an empty GUID is returned:
-//
-// {00000000-0000-0000-0000-000000000000}
-func (guid *GUID) String() string {
- if guid == nil {
- return emptyGUID
- }
-
- var c [38]byte
- c[0] = '{'
- putUint32Hex(c[1:9], guid.Data1)
- c[9] = '-'
- putUint16Hex(c[10:14], guid.Data2)
- c[14] = '-'
- putUint16Hex(c[15:19], guid.Data3)
- c[19] = '-'
- putByteHex(c[20:24], guid.Data4[0:2])
- c[24] = '-'
- putByteHex(c[25:37], guid.Data4[2:8])
- c[37] = '}'
- return string(c[:])
-}
-
-func putUint32Hex(b []byte, v uint32) {
- b[0] = hextable[byte(v>>24)>>4]
- b[1] = hextable[byte(v>>24)&0x0f]
- b[2] = hextable[byte(v>>16)>>4]
- b[3] = hextable[byte(v>>16)&0x0f]
- b[4] = hextable[byte(v>>8)>>4]
- b[5] = hextable[byte(v>>8)&0x0f]
- b[6] = hextable[byte(v)>>4]
- b[7] = hextable[byte(v)&0x0f]
-}
-
-func putUint16Hex(b []byte, v uint16) {
- b[0] = hextable[byte(v>>8)>>4]
- b[1] = hextable[byte(v>>8)&0x0f]
- b[2] = hextable[byte(v)>>4]
- b[3] = hextable[byte(v)&0x0f]
-}
-
-func putByteHex(dst, src []byte) {
- for i := 0; i < len(src); i++ {
- dst[i*2] = hextable[src[i]>>4]
- dst[i*2+1] = hextable[src[i]&0x0f]
- }
-}
-
-// IsEqualGUID compares two GUID.
-//
-// Not constant time comparison.
-func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool {
- return guid1.Data1 == guid2.Data1 &&
- guid1.Data2 == guid2.Data2 &&
- guid1.Data3 == guid2.Data3 &&
- guid1.Data4[0] == guid2.Data4[0] &&
- guid1.Data4[1] == guid2.Data4[1] &&
- guid1.Data4[2] == guid2.Data4[2] &&
- guid1.Data4[3] == guid2.Data4[3] &&
- guid1.Data4[4] == guid2.Data4[4] &&
- guid1.Data4[5] == guid2.Data4[5] &&
- guid1.Data4[6] == guid2.Data4[6] &&
- guid1.Data4[7] == guid2.Data4[7]
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/LICENSE b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/LICENSE
deleted file mode 100644
index af1894c87..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/LICENSE
+++ /dev/null
@@ -1,16 +0,0 @@
-ISC License (ISC)
-
-Copyright (c) 2020 John Chadwick
-Copyright (c) 2022 Wails Project Developers
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/README.md b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/README.md
deleted file mode 100644
index f3e020ec4..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Webviewloader
-
-Webviewloader is a port of [OpenWebView2Loader](https://github.com/jchv/OpenWebView2Loader) to Go.
-
-It is intended to be feature-complete with the original WebView2Loader distributed with
-the WebView2 NuGet package, but some features are intentionally not implemented.
-
-## Status
-
-- [x] CompareBrowserVersions
-- [x] CreateCoreWebView2Environment
-- [x] CreateCoreWebView2EnvironmentWithOptions
-- [x] GetAvailableCoreWebView2BrowserVersionString
-
-## Not implemented features
-
-- Registry Overrides of Parameters
-- Env Variable Overrides of Parameters
-- Does not incorporate `GetCurrentPackageInfo` to search for an installed runtime
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll
deleted file mode 100644
index cd1c694b8..000000000
Binary files a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/arm64/WebView2Loader.dll and /dev/null differ
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go
deleted file mode 100644
index 18bb26f71..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create.go
+++ /dev/null
@@ -1,177 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "syscall"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
- "golang.org/x/sys/windows"
-)
-
-func init() {
- // TODO: Set a flag here and output this message only if the flag is set in the application startup
- fmt.Println("DEB | Using go webview2loader")
- preventEnvAndRegistryOverrides()
-}
-
-type webView2RunTimeType int32
-
-const (
- webView2RunTimeTypeInstalled webView2RunTimeType = 0x00
- webView2RunTimeTypeRedistributable webView2RunTimeType = 0x01
-)
-
-// CreateCoreWebView2Environment creates an evergreen WebView2 Environment using the installed WebView2 Runtime version.
-//
-// This is equivalent to running CreateCoreWebView2EnvironmentWithOptions without any options.
-// For more information, see CreateCoreWebView2EnvironmentWithOptions.
-func CreateCoreWebView2Environment(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
- return CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler)
-}
-
-// CreateCoreWebView2EnvironmentWithOptions creates an environment with a custom version of WebView2 Runtime,
-// user data folder, and with or without additional options.
-//
-// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?#createcorewebview2environmentwithoptions
-func CreateCoreWebView2EnvironmentWithOptions(environmentCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, opts ...option) error {
- var params environmentOptions
- for _, opt := range opts {
- opt(¶ms)
- }
-
- var err error
- var dllPath string
- var runtimeType webView2RunTimeType
- if browserExecutableFolder := params.browserExecutableFolder; browserExecutableFolder != "" {
- runtimeType = webView2RunTimeTypeRedistributable
- dllPath, err = findEmbeddedClientDll(browserExecutableFolder)
- } else {
- runtimeType = webView2RunTimeTypeInstalled
- dllPath, _, err = findInstalledClientDll(params.preferCanary)
- }
-
- if err != nil {
- return err
- }
-
- return createWebViewEnvironmentWithClientDll(dllPath, runtimeType, params.userDataFolder,
- ¶ms, environmentCompletedHandler)
-}
-
-func createWebViewEnvironmentWithClientDll(lpLibFileName string, runtimeType webView2RunTimeType, userDataFolder string,
- envOptions *environmentOptions, envCompletedHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) error {
-
- if !filepath.IsAbs(lpLibFileName) {
- return fmt.Errorf("lpLibFileName must be absolute")
- }
-
- dll, err := windows.LoadDLL(lpLibFileName)
- if err != nil {
- return fmt.Errorf("Loading DLL failed: %w", err)
- }
-
- defer func() {
- canUnloadProc, err := dll.FindProc("DllCanUnloadNow")
- if err != nil {
- return
- }
-
- if r1, _, _ := canUnloadProc.Call(); r1 != windows.NO_ERROR {
- return
- }
-
- dll.Release()
- }()
-
- createProc, err := dll.FindProc("CreateWebViewEnvironmentWithOptionsInternal")
- if err != nil {
- return fmt.Errorf("Unable to find CreateWebViewEnvironmentWithOptionsInternal entrypoint: %w", err)
- }
-
- userDataPtr, err := windows.UTF16PtrFromString(userDataFolder)
- if err != nil {
- return err
- }
-
- envOptionsCom := combridge.New2[iCoreWebView2EnvironmentOptions, iCoreWebView2EnvironmentOptions2](
- envOptions, envOptions)
-
- defer envOptionsCom.Close()
-
- envCompletedHandler = &environmentCreatedHandler{envCompletedHandler}
- envCompletedCom := combridge.New[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](envCompletedHandler)
- defer envCompletedCom.Close()
-
- preventEnvAndRegistryOverrides()
-
- const unknown = 1
- hr, _, err := createProc.Call(
- uintptr(unknown),
- uintptr(runtimeType),
- uintptr(unsafe.Pointer(userDataPtr)),
- uintptr(envOptionsCom.Ref()),
- uintptr(envCompletedCom.Ref()))
-
- if hr != 0 {
- if err == nil || err == windows.ERROR_SUCCESS {
- err = syscall.Errno(hr)
- }
- return err
- }
-
- return nil
-}
-
-type environmentCreatedHandler struct {
- originalHandler ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-}
-
-func (r *environmentCreatedHandler) EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT {
- // The OpenWebview2Loader has some retry logic and retries once, didn't encounter any case when this would have been
- // needed during the development: https://github.com/jchv/OpenWebView2Loader/blob/master/Source/WebView2Loader.cpp#L202
-
- if createdEnvironment != nil {
- // May or may not be necessary, but the official WebView2Loader seems to do it.
- iidICoreWebView2Environment := windows.GUID{
- Data1: 0xb96d755e,
- Data2: 0x0319,
- Data3: 0x4e92,
- Data4: [8]byte{0xa2, 0x96, 0x23, 0x43, 0x6f, 0x46, 0xa1, 0xfc},
- }
-
- if err := createdEnvironment.QueryInterface(&iidICoreWebView2Environment, &createdEnvironment); err != nil {
- createdEnvironment = nil
- errNo, ok := err.(syscall.Errno)
- if !ok {
- errNo = syscall.Errno(windows.E_FAIL)
- }
- errorCode = HRESULT(errNo)
- }
- }
-
- r.originalHandler.EnvironmentCompleted(errorCode, createdEnvironment)
-
- if createdEnvironment != nil {
- createdEnvironment.Release()
- }
-
- return HRESULT(windows.S_OK)
-}
-
-func preventEnvAndRegistryOverrides() {
- // Setting these env variables to empty string also prevents registry overrides because webview2
- // checks for existence and not for empty value
- os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
- os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "")
- os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
-
- // The following seems not be be required because those are only used by the webview2loader which
- // in this case is implemented on our own. But nevertheless set them to empty to be consistent.
- os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", "")
- os.Setenv("WEBVIEW2_USER_DATA_FOLDER", "")
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_completed.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_completed.go
deleted file mode 100644
index 223c77e85..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_completed.go
+++ /dev/null
@@ -1,42 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
-)
-
-// HRESULT
-//
-// See https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
-type HRESULT int32
-
-// ICoreWebView2Environment Represents the WebView2 Environment
-//
-// See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2environment
-type ICoreWebView2Environment = combridge.IUnknownImpl
-
-// ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler receives the WebView2Environment created using CreateCoreWebView2Environment.
-type ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
- // EnvironmentCompleted is invoked to receive the created WebView2Environment
- //
- // See https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2createcorewebview2environmentcompletedhandler?#invoke
- EnvironmentCompleted(errorCode HRESULT, createdEnvironment *ICoreWebView2Environment) HRESULT
-}
-
-type iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler interface {
- combridge.IUnknown
- ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler
-}
-
-func init() {
- combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](
- "{4e8a3389-c9d8-4bd2-b6b5-124fee6cc14d}",
- _iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke,
- )
-}
-
-func _iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandlerInvoke(this uintptr, errorCode HRESULT, env *combridge.IUnknownImpl) uintptr {
- res := combridge.Resolve[iCoreWebView2CreateCoreWebView2EnvironmentCompletedHandler](this).EnvironmentCompleted(errorCode, env)
- return uintptr(res)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_options.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_options.go
deleted file mode 100644
index 4bae6064a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/env_create_options.go
+++ /dev/null
@@ -1,276 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "unicode/utf16"
- "unsafe"
-
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/combridge"
- "golang.org/x/sys/windows"
-)
-
-// WithBrowserExecutableFolder to specify whether WebView2 controls use a fixed or installed version
-// of the WebView2 Runtime that exists on a user machine.
-//
-// To use a fixed version of the WebView2 Runtime,
-// pass the folder path that contains the fixed version of the WebView2 Runtime.
-// BrowserExecutableFolder supports both relative (to the application's executable) and absolute files paths.
-// To create WebView2 controls that use the installed version of the WebView2 Runtime that exists on user
-// machines, pass a empty string to WithBrowserExecutableFolder. In this scenario, the API tries to find a
-// compatible version of the WebView2 Runtime that is installed on the user machine (first at the machine level,
-// and then per user) using the selected channel preference. The path of fixed version of the WebView2 Runtime
-// should not contain \Edge\Application\. When such a path is used, the API fails with HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).
-func WithBrowserExecutableFolder(folder string) option {
- return func(wvep *environmentOptions) {
- wvep.browserExecutableFolder = folder
- }
-}
-
-// WithUserDataFolder specifies to user data folder location for WebView2
-//
-// You may specify the userDataFolder to change the default user data folder location for WebView2.
-// The path is either an absolute file path or a relative file path that is interpreted as relative
-// to the compiled code for the current process.
-// Dhe default user data ({Executable File Name}.WebView2) folder is created in the same directory
-// next to the compiled code for the app. WebView2 creation fails if the compiled code is running
-// in a directory in which the process does not have permission to create a new directory.
-// The app is responsible to clean up the associated user data folder when it is done.
-func WithUserDataFolder(folder string) option {
- return func(wvep *environmentOptions) {
- wvep.userDataFolder = folder
- }
-}
-
-// WithAdditionalBrowserArguments changes the behavior of the WebView.
-//
-// The arguments are passed to the
-// browser process as part of the command. For more information about
-// using command-line switches with Chromium browser processes, navigate to
-// [Run Chromium with Flags][ChromiumDevelopersHowTosRunWithFlags].
-// The value appended to a switch is appended to the browser process, for
-// example, in `--edge-webview-switches=xxx` the value is `xxx`. If you
-// specify a switch that is important to WebView functionality, it is
-// ignored, for example, `--user-data-dir`. Specific features are disabled
-// internally and blocked from being enabled. If a switch is specified
-// multiple times, only the last instance is used.
-//
-// \> [!NOTE]\n\> A merge of the different values of the same switch is not attempted,
-// except for disabled and enabled features. The features specified by
-// `--enable-features` and `--disable-features` are merged with simple
-// logic.\n\> * The features is the union of the specified features
-// and built-in features. If a feature is disabled, it is removed from the
-// enabled features list.
-//
-// If you specify command-line switches and use the
-// `additionalBrowserArguments` parameter, the `--edge-webview-switches`
-// value takes precedence and is processed last. If a switch fails to
-// parse, the switch is ignored. The default state for the operation is
-// to run the browser process with no extra flags.
-//
-// [ChromiumDevelopersHowTosRunWithFlags]: https://www.chromium.org/developers/how-tos/run-chromium-with-flags "Run Chromium with flags | The Chromium Projects"
-func WithAdditionalBrowserArguments(args string) option {
- return func(wvep *environmentOptions) {
- wvep.additionalBrowserArguments = args
- }
-}
-
-// WithLanguage sets the default display language for WebView.
-//
-// It applies to browser UI such as
-// context menu and dialogs. It also applies to the `accept-languages` HTTP
-// header that WebView sends to websites. It is in the format of
-//
-// `language[-country]` where `language` is the 2-letter code from
-// [ISO 639][ISO639LanguageCodesHtml]
-// and `country` is the
-// 2-letter code from
-// [ISO 3166][ISOStandard72482Html].
-//
-// [ISO639LanguageCodesHtml]: https://www.iso.org/iso-639-language-codes.html "ISO 639 | ISO"
-// [ISOStandard72482Html]: https://www.iso.org/standard/72482.html "ISO 3166-1:2020 | ISO"
-func WithLanguage(lang string) option {
- return func(wvep *environmentOptions) {
- wvep.language = lang
- }
-}
-
-// WithTargetCompatibleBrowserVersion secifies the version of the WebView2 Runtime binaries required to be
-// compatible with your app.
-//
-// This defaults to the WebView2 Runtime version
-// that corresponds with the version of the SDK the app is using. The
-// format of this value is the same as the format of the
-// `BrowserVersionString` property and other `BrowserVersion` values. Only
-// the version part of the `BrowserVersion` value is respected. The channel
-// suffix, if it exists, is ignored. The version of the WebView2 Runtime
-// binaries actually used may be different from the specified
-// `TargetCompatibleBrowserVersion`. The binaries are only guaranteed to be
-// compatible. Verify the actual version on the `BrowserVersionString`
-// property on the `ICoreWebView2Environment`.
-func WithTargetCompatibleBrowserVersion(version string) option {
- return func(wvep *environmentOptions) {
- wvep.targetCompatibleBrowserVersion = version
- }
-}
-
-// WithAllowSingleSignOnUsingOSPrimaryAccount is used to enable
-// single sign on with Azure Active Directory (AAD) and personal Microsoft
-// Account (MSA) resources inside WebView. All AAD accounts, connected to
-// Windows and shared for all apps, are supported. For MSA, SSO is only enabled
-// for the account associated for Windows account login, if any.
-// Default is disabled. Universal Windows Platform apps must also declare
-// `enterpriseCloudSSO`
-// [Restricted capabilities][WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]
-// for the single sign on (SSO) to work.
-//
-// [WindowsUwpPackagingAppCapabilityDeclarationsRestrictedCapabilities]: /windows/uwp/packaging/app-capability-declarations\#restricted-capabilities "Restricted capabilities - App capability declarations | Microsoft Docs"
-func WithAllowSingleSignOnUsingOSPrimaryAccount(allow bool) option {
- return func(wvep *environmentOptions) {
- wvep.allowSingleSignOnUsingOSPrimaryAccount = allow
- }
-}
-
-// WithExclusiveUserDataFolderAccess specifies that the WebView environment
-// obtains exclusive access to the user data folder.
-//
-// If the user data folder is already being used by another WebView environment with a
-// different value for `ExclusiveUserDataFolderAccess` property, the creation of a WebView2Controller
-// using the environment object will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
-// When set as TRUE, no other WebView can be created from other processes using WebView2Environment
-// objects with the same UserDataFolder. This prevents other processes from creating WebViews
-// which share the same browser process instance, since sharing is performed among
-// WebViews that have the same UserDataFolder. When another process tries to create a
-// WebView2Controller from an WebView2Environment object created with the same user data folder,
-// it will fail with `HRESULT_FROM_WIN32(ERROR_INVALID_STATE)`.
-func WithExclusiveUserDataFolderAccess(exclusive bool) option {
- return func(wvep *environmentOptions) {
- wvep.exclusiveUserDataFolderAccess = exclusive
- }
-}
-
-type option func(*environmentOptions)
-
-var _ iCoreWebView2EnvironmentOptions = &environmentOptions{}
-var _ iCoreWebView2EnvironmentOptions2 = &environmentOptions{}
-
-type environmentOptions struct {
- browserExecutableFolder string
- userDataFolder string
- preferCanary bool
-
- additionalBrowserArguments string
- language string
- targetCompatibleBrowserVersion string
- allowSingleSignOnUsingOSPrimaryAccount bool
- exclusiveUserDataFolderAccess bool
-}
-
-func (o *environmentOptions) AdditionalBrowserArguments() string {
- return o.additionalBrowserArguments
-}
-
-func (o *environmentOptions) Language() string {
- return o.language
-}
-
-func (o *environmentOptions) TargetCompatibleBrowserVersion() string {
- v := o.targetCompatibleBrowserVersion
- if v == "" {
- v = kMinimumCompatibleVersion
- }
- return v
-}
-
-func (o *environmentOptions) AllowSingleSignOnUsingOSPrimaryAccount() bool {
- return o.allowSingleSignOnUsingOSPrimaryAccount
-}
-
-func (o *environmentOptions) ExclusiveUserDataFolderAccess() bool {
- return o.exclusiveUserDataFolderAccess
-}
-
-type iCoreWebView2EnvironmentOptions interface {
- combridge.IUnknown
-
- AdditionalBrowserArguments() string
- Language() string
- TargetCompatibleBrowserVersion() string
- AllowSingleSignOnUsingOSPrimaryAccount() bool
-}
-
-type iCoreWebView2EnvironmentOptions2 interface {
- combridge.IUnknown
-
- ExclusiveUserDataFolderAccess() bool
-}
-
-func init() {
- combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions](
- "{2fde08a8-1e9a-4766-8c05-95a9ceb9d1c5}",
- _iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments,
- _iCoreWebView2EnvironmentOptionsNOP,
- _iCoreWebView2EnvironmentOptionsLanguage,
- _iCoreWebView2EnvironmentOptionsNOP,
- _iCoreWebView2EnvironmentTargetCompatibleBrowserVersion,
- _iCoreWebView2EnvironmentOptionsNOP,
- _iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount,
- _iCoreWebView2EnvironmentOptionsNOP,
- )
-
- combridge.RegisterVTable[combridge.IUnknown, iCoreWebView2EnvironmentOptions2](
- "{ff85c98a-1ba7-4a6b-90c8-2b752c89e9e2}",
- _iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess,
- _iCoreWebView2EnvironmentOptionsNOP,
- )
-}
-func _iCoreWebView2EnvironmentOptionsNOP(this uintptr) uintptr {
- return uintptr(windows.S_FALSE)
-}
-
-func _iCoreWebView2EnvironmentOptionsAdditionalBrowserArguments(this uintptr, value **uint16) uintptr {
- v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AdditionalBrowserArguments()
- *value = stringToOleString(v)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentOptionsLanguage(this uintptr, value **uint16) uintptr {
- args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).Language()
- *value = stringToOleString(args)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentTargetCompatibleBrowserVersion(this uintptr, value **uint16) uintptr {
- args := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).TargetCompatibleBrowserVersion()
- *value = stringToOleString(args)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentOptionsAllowSingleSignOnUsingOSPrimaryAccount(this uintptr, value *int32) uintptr {
- v := combridge.Resolve[iCoreWebView2EnvironmentOptions](this).AllowSingleSignOnUsingOSPrimaryAccount()
- *value = boolToInt(v)
- return uintptr(windows.S_OK)
-}
-
-func _iCoreWebView2EnvironmentOptions2ExclusiveUserDataFolderAccess(this uintptr, value *int32) uintptr {
- v := combridge.Resolve[iCoreWebView2EnvironmentOptions2](this).ExclusiveUserDataFolderAccess()
- *value = boolToInt(v)
- return uintptr(windows.S_OK)
-}
-
-func stringToOleString(v string) *uint16 {
- wstr := utf16.Encode([]rune(v + "\x00"))
- lwstr := len(wstr)
- ptr := (*uint16)(coTaskMemAlloc(2 * lwstr))
-
- copy(unsafe.Slice(ptr, lwstr), wstr)
-
- return ptr
-}
-
-func boolToInt(v bool) int32 {
- if v {
- return 1
- }
- return 0
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll.go
deleted file mode 100644
index da9472ff1..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll.go
+++ /dev/null
@@ -1,74 +0,0 @@
-//go:build windows
-
-package webviewloader
-
-import (
- "errors"
- "fmt"
- "os"
- "path/filepath"
- "runtime"
-
- "golang.org/x/sys/windows/registry"
-)
-
-var (
- errNoClientDLLFound = errors.New("no webview2 found")
-)
-
-func findEmbeddedBrowserVersion(filename string) (string, error) {
- block, err := getFileVersionInfo(filename)
- if err != nil {
- return "", err
- }
-
- info, err := verQueryValueString(block, "\\StringFileInfo\\040904B0\\ProductVersion")
- if err != nil {
- return "", err
- }
-
- return info, nil
-}
-
-func findEmbeddedClientDll(embeddedEdgeSubFolder string) (outClientPath string, err error) {
- if !filepath.IsAbs(embeddedEdgeSubFolder) {
- exe, err := os.Executable()
- if err != nil {
- return "", err
- }
-
- embeddedEdgeSubFolder = filepath.Join(filepath.Dir(exe), embeddedEdgeSubFolder)
- }
-
- return findClientDllInFolder(embeddedEdgeSubFolder)
-}
-
-func findClientDllInFolder(folder string) (string, error) {
- arch := ""
- switch runtime.GOARCH {
- case "arm64":
- arch = "arm64"
- case "amd64":
- arch = "x64"
- case "386":
- arch = "x86"
- default:
- return "", fmt.Errorf("Unsupported architecture")
- }
-
- dllPath := filepath.Join(folder, "EBWebView", arch, "EmbeddedBrowserWebView.dll")
- if _, err := os.Stat(dllPath); err != nil {
- return "", mapFindErr(err)
- }
- return dllPath, nil
-}
-
-func mapFindErr(err error) error {
- if errors.Is(err, registry.ErrNotExist) {
- return errNoClientDLLFound
- }
- if errors.Is(err, os.ErrNotExist) {
- return errNoClientDLLFound
- }
- return err
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll_installed.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll_installed.go
deleted file mode 100644
index 7ee171b2a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/find_dll_installed.go
+++ /dev/null
@@ -1,94 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "path/filepath"
-
- "golang.org/x/sys/windows/registry"
-)
-
-const (
- kNumChannels = 4
- kInstallKeyPath = "Software\\Microsoft\\EdgeUpdate\\ClientState\\"
- kMinimumCompatibleVersion = "86.0.616.0"
-)
-
-var (
- kChannelName = [kNumChannels]string{
- "", "beta", "dev", "canary", // "internal"
- }
-
- kChannelUuid = [kNumChannels]string{
- "{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}",
- "{2CD8A007-E189-409D-A2C8-9AF4EF3C72AA}",
- "{0D50BFEC-CD6A-4F9A-964C-C7416E3ACB10}",
- "{65C35B14-6C1D-4122-AC46-7148CC9D6497}",
- //"{BE59E8FD-089A-411B-A3B0-051D9E417818}",
- }
-
- minimumCompatibleVersion, _ = parseVersion(kMinimumCompatibleVersion)
-)
-
-func findInstalledClientDll(preferCanary bool) (clientPath string, version *version, err error) {
- for i := 0; i < kNumChannels; i++ {
- channel := i
- if preferCanary {
- channel = (kNumChannels - 1) - i
- }
-
- key := kInstallKeyPath + kChannelUuid[channel]
- for _, checkSystem := range []bool{true, false} {
- clientPath, version, err := findInstalledClientDllForChannel(key, checkSystem)
- if err == errNoClientDLLFound {
- continue
- }
- if err != nil {
- return "", nil, err
- }
-
- version.channel = kChannelName[channel]
- return clientPath, version, nil
- }
- }
- return "", nil, errNoClientDLLFound
-}
-
-func findInstalledClientDllForChannel(subKey string, system bool) (clientPath string, clientVersion *version, err error) {
- key := registry.LOCAL_MACHINE
- if !system {
- key = registry.CURRENT_USER
- }
-
- regKey, err := registry.OpenKey(key, subKey, registry.READ|registry.WOW64_32KEY)
- if err != nil {
- return "", nil, mapFindErr(err)
- }
- defer regKey.Close()
-
- embeddedEdgeSubFolder, _, err := regKey.GetStringValue("EBWebView")
- if err != nil {
- return "", nil, mapFindErr(err)
- }
-
- if embeddedEdgeSubFolder == "" {
- return "", nil, errNoClientDLLFound
- }
-
- versionString := filepath.Base(embeddedEdgeSubFolder)
- version, err := parseVersion(versionString)
- if err != nil {
- return "", nil, errNoClientDLLFound
- }
-
- if version.compare(minimumCompatibleVersion) < 0 {
- return "", nil, errNoClientDLLFound
- }
-
- dllPath, err := findEmbeddedClientDll(embeddedEdgeSubFolder)
- if err != nil {
- return "", nil, mapFindErr(err)
- }
-
- return dllPath, &version, nil
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module.go
deleted file mode 100644
index 3e02fe985..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module.go
+++ /dev/null
@@ -1,173 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import (
- "errors"
- "fmt"
- "os"
- "sync"
- "unsafe"
-
- "github.com/jchv/go-winloader"
-
- "golang.org/x/sys/windows"
-)
-
-func init() {
- preventEnvAndRegistryOverrides(nil, nil, "")
-}
-
-var (
- memOnce sync.Once
- memModule winloader.Module
- memCreate winloader.Proc
- memCompareBrowserVersions winloader.Proc
- memGetAvailableCoreWebView2BrowserVersionString winloader.Proc
- memErr error
-)
-
-const (
- // https://referencesource.microsoft.com/#system.web/Util/hresults.cs,20
- E_FILENOTFOUND = 0x80070002
-)
-
-// CompareBrowserVersions will compare the 2 given versions and return:
-//
-// Less than zero: v1 < v2
-// zero: v1 == v2
-// Greater than zero: v1 > v2
-func CompareBrowserVersions(v1 string, v2 string) (int, error) {
- _v1, err := windows.UTF16PtrFromString(v1)
- if err != nil {
- return 0, err
- }
- _v2, err := windows.UTF16PtrFromString(v2)
- if err != nil {
- return 0, err
- }
-
- err = loadFromMemory()
- if err != nil {
- return 0, err
- }
-
- var result int32
- _, _, err = memCompareBrowserVersions.Call(
- uint64(uintptr(unsafe.Pointer(_v1))),
- uint64(uintptr(unsafe.Pointer(_v2))),
- uint64(uintptr(unsafe.Pointer(&result))))
-
- if err != windows.ERROR_SUCCESS {
- return 0, err
- }
- return int(result), nil
-}
-
-// GetAvailableCoreWebView2BrowserVersionString returns version of the webview2 runtime.
-// If path is empty, it will try to find installed webview2 is the system.
-// If there is no version installed, a blank string is returned.
-func GetAvailableCoreWebView2BrowserVersionString(path string) (string, error) {
- if path != "" {
- // The default implementation fails if CGO and a fixed browser path is used. It's caused by the go-winloader
- // which loads the native DLL from memory.
- // Use the new GoWebView2Loader in this case, in the future we will make GoWebView2Loader
- // feature-complete and remove the use of the native DLL and go-winloader.
- version, err := goGetAvailableCoreWebView2BrowserVersionString(path)
- if errors.Is(err, errNoClientDLLFound) {
- // WebView2 is not found
- return "", nil
- } else if err != nil {
- return "", err
- }
-
- return version, nil
- }
-
- err := loadFromMemory()
- if err != nil {
- return "", err
- }
-
- var browserPath *uint16 = nil
- if path != "" {
- browserPath, err = windows.UTF16PtrFromString(path)
- if err != nil {
- return "", fmt.Errorf("error calling UTF16PtrFromString for %s: %v", path, err)
- }
- }
-
- preventEnvAndRegistryOverrides(browserPath, nil, "")
- var result *uint16
- res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call(
- uint64(uintptr(unsafe.Pointer(browserPath))),
- uint64(uintptr(unsafe.Pointer(&result))))
-
- if res != 0 {
- if res == E_FILENOTFOUND {
- // WebView2 is not installed
- return "", nil
- }
-
- return "", fmt.Errorf("Unable to call GetAvailableCoreWebView2BrowserVersionString (%x): %w", res, err)
- }
-
- version := windows.UTF16PtrToString(result)
- windows.CoTaskMemFree(unsafe.Pointer(result))
- return version, nil
-}
-
-// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and
-// call the CreateCoreWebView2EnvironmentWithOptions routine.
-func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentCompletedHandle uintptr, additionalBrowserArgs string) (uintptr, error) {
- err := loadFromMemory()
- if err != nil {
- return 0, err
- }
-
- preventEnvAndRegistryOverrides(browserExecutableFolder, userDataFolder, additionalBrowserArgs)
- res, _, _ := memCreate.Call(
- uint64(uintptr(unsafe.Pointer(browserExecutableFolder))),
- uint64(uintptr(unsafe.Pointer(userDataFolder))),
- 0,
- uint64(environmentCompletedHandle),
- )
- return uintptr(res), nil
-}
-
-func loadFromMemory() error {
- var err error
- // DLL is not available natively. Try loading embedded copy.
- memOnce.Do(func() {
- memModule, memErr = winloader.LoadFromMemory(WebView2Loader)
- if memErr != nil {
- err = fmt.Errorf("Unable to load WebView2Loader.dll from memory: %w", memErr)
- return
- }
- memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions")
- memCompareBrowserVersions = memModule.Proc("CompareBrowserVersions")
- memGetAvailableCoreWebView2BrowserVersionString = memModule.Proc("GetAvailableCoreWebView2BrowserVersionString")
- })
- return err
-}
-
-func preventEnvAndRegistryOverrides(browserFolder, userDataFolder *uint16, additionalBrowserArgs string) {
- // Setting these env variables to empty string also prevents registry overrides because webview2loader
- // checks for existence and not for empty value
- os.Setenv("WEBVIEW2_PIPE_FOR_SCRIPT_DEBUGGER", "")
-
- // Set these overrides to the values or empty to prevent registry and external env overrides
- os.Setenv("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", additionalBrowserArgs)
- os.Setenv("WEBVIEW2_RELEASE_CHANNEL_PREFERENCE", "0")
- os.Setenv("WEBVIEW2_BROWSER_EXECUTABLE_FOLDER", windows.UTF16PtrToString(browserFolder))
- os.Setenv("WEBVIEW2_USER_DATA_FOLDER", windows.UTF16PtrToString(userDataFolder))
-}
-
-func goGetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
- clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
- if err != nil {
- return "", err
- }
-
- return findEmbeddedBrowserVersion(clientPath)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_386.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_386.go
deleted file mode 100644
index e4ff44ff3..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_386.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import _ "embed"
-
-//go:embed x86/WebView2Loader.dll
-var WebView2Loader []byte
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_amd64.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_amd64.go
deleted file mode 100644
index 27423ae8a..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_amd64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import _ "embed"
-
-//go:embed x64/WebView2Loader.dll
-var WebView2Loader []byte
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_arm64.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_arm64.go
deleted file mode 100644
index bba6a88cb..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/native_module_arm64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build windows && native_webview2loader
-
-package webviewloader
-
-import _ "embed"
-
-//go:embed arm64/WebView2Loader.dll
-var WebView2Loader []byte
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/syscall.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/syscall.go
deleted file mode 100644
index 24d0856a5..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/syscall.go
+++ /dev/null
@@ -1,143 +0,0 @@
-//go:build windows
-
-package webviewloader
-
-import (
- "fmt"
- "syscall"
- "unicode/utf16"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var (
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
- procGlobalAlloc = modkernel32.NewProc("GlobalAlloc")
- procGlobalFree = modkernel32.NewProc("GlobalFree")
-
- modversion = windows.NewLazySystemDLL("version.dll")
- procGetFileVersionInfoSize = modversion.NewProc("GetFileVersionInfoSizeW")
- procGetFileVersionInfo = modversion.NewProc("GetFileVersionInfoW")
- procVerQueryValue = modversion.NewProc("VerQueryValueW")
-
- modole32 = windows.NewLazySystemDLL("ole32.dll")
- procCoTaskMemAlloc = modole32.NewProc("CoTaskMemAlloc")
-)
-
-func getFileVersionInfo(path string) ([]byte, error) {
- lptstrFilename, err := syscall.UTF16PtrFromString(path)
- if err != nil {
- return nil, err
- }
-
- size, _, err := procGetFileVersionInfoSize.Call(
- uintptr(unsafe.Pointer(lptstrFilename)),
- 0,
- )
-
- err = maskErrorSuccess(err)
- if size == 0 && err == nil {
- err = fmt.Errorf("GetFileVersionInfoSize failed")
- }
-
- if err != nil {
- return nil, err
- }
-
- data := make([]byte, size)
- ret, _, err := procGetFileVersionInfo.Call(
- uintptr(unsafe.Pointer(lptstrFilename)),
- 0,
- uintptr(size),
- uintptr(unsafe.Pointer(&data[0])),
- )
-
- err = maskErrorSuccess(err)
- if ret == 0 && err == nil {
- err = fmt.Errorf("GetFileVersionInfo failed")
- }
-
- if err != nil {
- return nil, err
- }
- return data, nil
-}
-
-func verQueryValueString(block []byte, subBlock string) (string, error) {
- // Allocate memory from native side to make sure the block doesn't get moved
- // because we get a pointer into that memory block from the native verQueryValue
- // call back.
- pBlock := globalAlloc(0, uint32(len(block)))
- defer globalFree(unsafe.Pointer(pBlock))
-
- // Copy the memory region into native side memory
- copy(unsafe.Slice((*byte)(pBlock), len(block)), block)
-
- lpSubBlock, err := syscall.UTF16PtrFromString(subBlock)
- if err != nil {
- return "", err
- }
-
- var lplpBuffer unsafe.Pointer
- var puLen uint
- ret, _, err := procVerQueryValue.Call(
- uintptr(pBlock),
- uintptr(unsafe.Pointer(lpSubBlock)),
- uintptr(unsafe.Pointer(&lplpBuffer)),
- uintptr(unsafe.Pointer(&puLen)),
- )
-
- err = maskErrorSuccess(err)
- if ret == 0 && err == nil {
- err = fmt.Errorf("VerQueryValue failed")
- }
-
- if err != nil {
- return "", err
- }
-
- if puLen <= 1 {
- return "", nil
- }
- puLen -= 1 // Remove Null-Terminator
-
- wchar := unsafe.Slice((*uint16)(lplpBuffer), puLen)
- return string(utf16.Decode(wchar)), nil
-}
-
-func globalAlloc(uFlags uint, dwBytes uint32) unsafe.Pointer {
- ret, _, _ := procGlobalAlloc.Call(
- uintptr(uFlags),
- uintptr(dwBytes))
-
- if ret == 0 {
- panic("globalAlloc failed")
- }
-
- return unsafe.Pointer(ret)
-}
-
-func globalFree(data unsafe.Pointer) {
- ret, _, _ := procGlobalFree.Call(uintptr(data))
- if ret != 0 {
- panic("globalFree failed")
- }
-}
-
-func maskErrorSuccess(err error) error {
- if err == windows.ERROR_SUCCESS {
- return nil
- }
- return err
-}
-
-func coTaskMemAlloc(size int) unsafe.Pointer {
- ret, _, _ := procCoTaskMemAlloc.Call(
- uintptr(size))
-
- if ret == 0 {
- panic("coTaskMemAlloc failed")
- }
- return unsafe.Pointer(ret)
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/version.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/version.go
deleted file mode 100644
index cf278d950..000000000
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/version.go
+++ /dev/null
@@ -1,147 +0,0 @@
-//go:build windows && !native_webview2loader
-
-package webviewloader
-
-import (
- "errors"
- "fmt"
- "strconv"
- "strings"
-)
-
-// CompareBrowserVersions will compare the 2 given versions and return:
-//
-// -1 = v1 < v2
-// 0 = v1 == v2
-// 1 = v1 > v2
-func CompareBrowserVersions(v1 string, v2 string) (int, error) {
- v, err := parseVersion(v1)
- if err != nil {
- return 0, fmt.Errorf("v1 invalid: %w", err)
- }
-
- w, err := parseVersion(v2)
- if err != nil {
- return 0, fmt.Errorf("v2 invalid: %w", err)
- }
-
- return v.compare(w), nil
-}
-
-// GetAvailableCoreWebView2BrowserVersionString get the browser version info including channel name
-// if it is the WebView2 Runtime.
-// Channel names are Beta, Dev, and Canary.
-func GetAvailableCoreWebView2BrowserVersionString(browserExecutableFolder string) (string, error) {
- if browserExecutableFolder != "" {
- clientPath, err := findEmbeddedClientDll(browserExecutableFolder)
- if errors.Is(err, errNoClientDLLFound) {
- // WebView2 is not found
- return "", nil
- } else if err != nil {
- return "", err
- }
-
- return findEmbeddedBrowserVersion(clientPath)
- }
-
- _, version, err := findInstalledClientDll(false)
- if errors.Is(err, errNoClientDLLFound) {
- return "", nil
- } else if err != nil {
- return "", err
- }
-
- return version.String(), nil
-}
-
-type version struct {
- major int
- minor int
- patch int
- build int
-
- channel string
-}
-
-func (v version) String() string {
- vv := fmt.Sprintf("%d.%d.%d.%d", v.major, v.minor, v.patch, v.build)
- if v.channel != "" {
- vv += " " + v.channel
- }
-
- return vv
-}
-
-func (v version) compare(o version) int {
- if c := compareInt(v.major, o.major); c != 0 {
- return c
- }
- if c := compareInt(v.minor, o.minor); c != 0 {
- return c
- }
- if c := compareInt(v.patch, o.patch); c != 0 {
- return c
- }
- return compareInt(v.build, o.build)
-}
-
-func parseVersion(v string) (version, error) {
- var p version
-
- // Split away channel information...
- if i := strings.Index(v, " "); i > 0 {
- p.channel = v[i+1:]
- v = v[:i]
- }
-
- vv := strings.Split(v, ".")
- if len(vv) > 4 {
- return p, fmt.Errorf("too many version parts")
- }
-
- var err error
- vv, p.major, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad major version: %w", err)
- }
-
- vv, p.minor, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad minor version: %w", err)
- }
-
- vv, p.patch, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad patch version: %w", err)
- }
-
- _, p.build, err = parseInt(vv)
- if err != nil {
- return p, fmt.Errorf("bad build version: %w", err)
- }
-
- return p, nil
-}
-
-func parseInt(v []string) ([]string, int, error) {
- if len(v) == 0 {
- return nil, 0, nil
- }
-
- p, err := strconv.ParseInt(v[0], 10, 32)
- if err != nil {
- return nil, 0, err
- }
- return v[1:], int(p), nil
-}
-
-func compareInt(v1, v2 int) int {
- if v1 == v2 {
- return 0
- }
- if v1 < v2 {
- return -1
- } else {
- return +1
- }
-}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll
deleted file mode 100644
index ab15cffb4..000000000
Binary files a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x64/WebView2Loader.dll and /dev/null differ
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll
deleted file mode 100644
index 8609d58ee..000000000
Binary files a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/x86/WebView2Loader.dll and /dev/null differ
diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go
index 43ec57c72..a513e875a 100644
--- a/v2/internal/frontend/desktop/windows/window.go
+++ b/v2/internal/frontend/desktop/windows/window.go
@@ -3,11 +3,10 @@
package windows
import (
+ "github.com/wailsapp/go-webview2/pkg/edge"
"sync"
"unsafe"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
-
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
diff --git a/v2/internal/frontend/dispatcher/calls.go b/v2/internal/frontend/dispatcher/calls.go
index ef19c6030..491d17fe2 100644
--- a/v2/internal/frontend/dispatcher/calls.go
+++ b/v2/internal/frontend/dispatcher/calls.go
@@ -3,8 +3,9 @@ package dispatcher
import (
"encoding/json"
"fmt"
- "github.com/wailsapp/wails/v2/internal/frontend"
"strings"
+
+ "github.com/wailsapp/wails/v2/internal/frontend"
)
type callMessage struct {
@@ -49,7 +50,12 @@ func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend
CallbackID: payload.CallbackID,
}
if err != nil {
- callbackMessage.Err = err.Error()
+ // Use the error formatter if one was provided
+ if d.errfmt != nil {
+ callbackMessage.Err = d.errfmt(err)
+ } else {
+ callbackMessage.Err = err.Error()
+ }
} else {
callbackMessage.Result = result
}
@@ -66,7 +72,7 @@ func (d *Dispatcher) processCallMessage(message string, sender frontend.Frontend
// CallbackMessage defines a message that contains the result of a call
type CallbackMessage struct {
Result interface{} `json:"result"`
- Err string `json:"error"`
+ Err any `json:"error"`
CallbackID string `json:"callbackid"`
}
diff --git a/v2/internal/frontend/dispatcher/dispatcher.go b/v2/internal/frontend/dispatcher/dispatcher.go
index 44a8886e5..56092d370 100644
--- a/v2/internal/frontend/dispatcher/dispatcher.go
+++ b/v2/internal/frontend/dispatcher/dispatcher.go
@@ -7,6 +7,7 @@ import (
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options"
)
type Dispatcher struct {
@@ -15,15 +16,17 @@ type Dispatcher struct {
events frontend.Events
bindingsDB *binding.DB
ctx context.Context
+ errfmt options.ErrorFormatter
}
-func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events) *Dispatcher {
+func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events, errfmt options.ErrorFormatter) *Dispatcher {
return &Dispatcher{
log: log,
bindings: bindings,
events: events,
bindingsDB: bindings.DB(),
ctx: ctx,
+ errfmt: errfmt,
}
}
diff --git a/v2/internal/frontend/runtime/desktop/contextmenu.js b/v2/internal/frontend/runtime/desktop/contextmenu.js
new file mode 100644
index 000000000..b9c397546
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/contextmenu.js
@@ -0,0 +1,50 @@
+/*
+--default-contextmenu: auto; (default) will show the default context menu if contentEditable is true OR text has been selected OR element is input or textarea
+--default-contextmenu: show; will always show the default context menu
+--default-contextmenu: hide; will always hide the default context menu
+
+This rule is inherited like normal CSS rules, so nesting works as expected
+*/
+export function processDefaultContextMenu(event) {
+ // Process default context menu
+ const element = event.target;
+ const computedStyle = window.getComputedStyle(element);
+ const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim();
+ switch (defaultContextMenuAction) {
+ case "show":
+ return;
+ case "hide":
+ event.preventDefault();
+ return;
+ default:
+ // Check if contentEditable is true
+ if (element.isContentEditable) {
+ return;
+ }
+
+ // Check if text has been selected and action is on the selected elements
+ const selection = window.getSelection();
+ const hasSelection = (selection.toString().length > 0)
+ if (hasSelection) {
+ for (let i = 0; i < selection.rangeCount; i++) {
+ const range = selection.getRangeAt(i);
+ const rects = range.getClientRects();
+ for (let j = 0; j < rects.length; j++) {
+ const rect = rects[j];
+ if (document.elementFromPoint(rect.left, rect.top) === element) {
+ return;
+ }
+ }
+ }
+ }
+ // Check if tagname is input or textarea
+ if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") {
+ if (hasSelection || (!element.readOnly && !element.disabled)) {
+ return;
+ }
+ }
+
+ // hide default context menu
+ event.preventDefault();
+ }
+}
diff --git a/v2/internal/frontend/runtime/desktop/main.js b/v2/internal/frontend/runtime/desktop/main.js
index 9ec68acd6..65d954d95 100644
--- a/v2/internal/frontend/runtime/desktop/main.js
+++ b/v2/internal/frontend/runtime/desktop/main.js
@@ -16,6 +16,7 @@ import * as Window from "./window";
import * as Screen from "./screen";
import * as Browser from "./browser";
import * as Clipboard from "./clipboard";
+import * as ContextMenu from "./contextmenu";
export function Quit() {
@@ -61,7 +62,7 @@ window.wails = {
callbacks,
flags: {
disableScrollbarDrag: false,
- disableWailsDefaultContextMenu: false,
+ disableDefaultContextMenu: false,
enableResize: false,
defaultCursor: null,
borderThickness: 6,
@@ -78,10 +79,8 @@ if (window.wailsbindings) {
delete window.wails.SetBindings;
}
-// This is evaluated at build time in package.json
-// const dev = 0;
-// const production = 1;
-if (ENV === 1) {
+// (bool) This is evaluated at build time in package.json
+if (!DEBUG) {
delete window.wailsbindings;
}
@@ -189,8 +188,13 @@ window.addEventListener('mousemove', function (e) {
// Setup context menu hook
window.addEventListener('contextmenu', function (e) {
- if (window.wails.flags.disableWailsDefaultContextMenu) {
+ // always show the contextmenu in debug & dev
+ if (DEBUG) return;
+
+ if (window.wails.flags.disableDefaultContextMenu) {
e.preventDefault();
+ } else {
+ ContextMenu.processDefaultContextMenu(e);
}
});
diff --git a/v2/internal/frontend/runtime/package.json b/v2/internal/frontend/runtime/package.json
index aa6c3aad5..09ff4d50f 100644
--- a/v2/internal/frontend/runtime/package.json
+++ b/v2/internal/frontend/runtime/package.json
@@ -7,8 +7,8 @@
"build": "run-p build:*",
"build:ipc-desktop": "npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js",
"build:ipc-dev": "cd dev && npm install && npm run build",
- "build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1",
- "build:runtime-desktop-dev": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0",
+ "build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:DEBUG=false",
+ "build:runtime-desktop-debug": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_debug_desktop.js --define:DEBUG=true",
"test": "vitest"
},
"author": "Lea Anthony ",
diff --git a/v2/internal/frontend/runtime/runtime_debug_desktop.go b/v2/internal/frontend/runtime/runtime_debug_desktop.go
new file mode 100644
index 000000000..8dff343c0
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_debug_desktop.go
@@ -0,0 +1,8 @@
+//go:build debug || !production
+
+package runtime
+
+import _ "embed"
+
+//go:embed runtime_debug_desktop.js
+var RuntimeDesktopJS []byte
diff --git a/v2/internal/frontend/runtime/runtime_debug_desktop.js b/v2/internal/frontend/runtime/runtime_debug_desktop.js
new file mode 100644
index 000000000..e680df85d
--- /dev/null
+++ b/v2/internal/frontend/runtime/runtime_debug_desktop.js
@@ -0,0 +1,621 @@
+(() => {
+ var __defProp = Object.defineProperty;
+ var __export = (target, all) => {
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+ };
+
+ // desktop/log.js
+ var log_exports = {};
+ __export(log_exports, {
+ LogDebug: () => LogDebug,
+ LogError: () => LogError,
+ LogFatal: () => LogFatal,
+ LogInfo: () => LogInfo,
+ LogLevel: () => LogLevel,
+ LogPrint: () => LogPrint,
+ LogTrace: () => LogTrace,
+ LogWarning: () => LogWarning,
+ SetLogLevel: () => SetLogLevel
+ });
+ function sendLogMessage(level, message) {
+ window.WailsInvoke("L" + level + message);
+ }
+ function LogTrace(message) {
+ sendLogMessage("T", message);
+ }
+ function LogPrint(message) {
+ sendLogMessage("P", message);
+ }
+ function LogDebug(message) {
+ sendLogMessage("D", message);
+ }
+ function LogInfo(message) {
+ sendLogMessage("I", message);
+ }
+ function LogWarning(message) {
+ sendLogMessage("W", message);
+ }
+ function LogError(message) {
+ sendLogMessage("E", message);
+ }
+ function LogFatal(message) {
+ sendLogMessage("F", message);
+ }
+ function SetLogLevel(loglevel) {
+ sendLogMessage("S", loglevel);
+ }
+ var LogLevel = {
+ TRACE: 1,
+ DEBUG: 2,
+ INFO: 3,
+ WARNING: 4,
+ ERROR: 5
+ };
+
+ // desktop/events.js
+ var Listener = class {
+ constructor(eventName, callback, maxCallbacks) {
+ this.eventName = eventName;
+ this.maxCallbacks = maxCallbacks || -1;
+ this.Callback = (data) => {
+ callback.apply(null, data);
+ if (this.maxCallbacks === -1) {
+ return false;
+ }
+ this.maxCallbacks -= 1;
+ return this.maxCallbacks === 0;
+ };
+ }
+ };
+ var eventListeners = {};
+ function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ eventListeners[eventName] = eventListeners[eventName] || [];
+ const thisListener = new Listener(eventName, callback, maxCallbacks);
+ eventListeners[eventName].push(thisListener);
+ return () => listenerOff(thisListener);
+ }
+ function EventsOn(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, -1);
+ }
+ function EventsOnce(eventName, callback) {
+ return EventsOnMultiple(eventName, callback, 1);
+ }
+ function notifyListeners(eventData) {
+ let eventName = eventData.name;
+ if (eventListeners[eventName]) {
+ const newEventListenerList = eventListeners[eventName].slice();
+ for (let count = eventListeners[eventName].length - 1; count >= 0; count -= 1) {
+ const listener = eventListeners[eventName][count];
+ let data = eventData.data;
+ const destroy = listener.Callback(data);
+ if (destroy) {
+ newEventListenerList.splice(count, 1);
+ }
+ }
+ if (newEventListenerList.length === 0) {
+ removeListener(eventName);
+ } else {
+ eventListeners[eventName] = newEventListenerList;
+ }
+ }
+ }
+ function EventsNotify(notifyMessage) {
+ let message;
+ try {
+ message = JSON.parse(notifyMessage);
+ } catch (e) {
+ const error = "Invalid JSON passed to Notify: " + notifyMessage;
+ throw new Error(error);
+ }
+ notifyListeners(message);
+ }
+ function EventsEmit(eventName) {
+ const payload = {
+ name: eventName,
+ data: [].slice.apply(arguments).slice(1)
+ };
+ notifyListeners(payload);
+ window.WailsInvoke("EE" + JSON.stringify(payload));
+ }
+ function removeListener(eventName) {
+ delete eventListeners[eventName];
+ window.WailsInvoke("EX" + eventName);
+ }
+ function EventsOff(eventName, ...additionalEventNames) {
+ removeListener(eventName);
+ if (additionalEventNames.length > 0) {
+ additionalEventNames.forEach((eventName2) => {
+ removeListener(eventName2);
+ });
+ }
+ }
+ function listenerOff(listener) {
+ const eventName = listener.eventName;
+ eventListeners[eventName] = eventListeners[eventName].filter((l) => l !== listener);
+ if (eventListeners[eventName].length === 0) {
+ removeListener(eventName);
+ }
+ }
+
+ // desktop/calls.js
+ var callbacks = {};
+ function cryptoRandom() {
+ var array = new Uint32Array(1);
+ return window.crypto.getRandomValues(array)[0];
+ }
+ function basicRandom() {
+ return Math.random() * 9007199254740991;
+ }
+ var randomFunc;
+ if (window.crypto) {
+ randomFunc = cryptoRandom;
+ } else {
+ randomFunc = basicRandom;
+ }
+ function Call(name, args, timeout) {
+ if (timeout == null) {
+ timeout = 0;
+ }
+ return new Promise(function(resolve, reject) {
+ var callbackID;
+ do {
+ callbackID = name + "-" + randomFunc();
+ } while (callbacks[callbackID]);
+ var timeoutHandle;
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function() {
+ reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
+ }, timeout);
+ }
+ callbacks[callbackID] = {
+ timeoutHandle,
+ reject,
+ resolve
+ };
+ try {
+ const payload = {
+ name,
+ args,
+ callbackID
+ };
+ window.WailsInvoke("C" + JSON.stringify(payload));
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ }
+ window.ObfuscatedCall = (id, args, timeout) => {
+ if (timeout == null) {
+ timeout = 0;
+ }
+ return new Promise(function(resolve, reject) {
+ var callbackID;
+ do {
+ callbackID = id + "-" + randomFunc();
+ } while (callbacks[callbackID]);
+ var timeoutHandle;
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function() {
+ reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID));
+ }, timeout);
+ }
+ callbacks[callbackID] = {
+ timeoutHandle,
+ reject,
+ resolve
+ };
+ try {
+ const payload = {
+ id,
+ args,
+ callbackID
+ };
+ window.WailsInvoke("c" + JSON.stringify(payload));
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ };
+ function Callback(incomingMessage) {
+ let message;
+ try {
+ message = JSON.parse(incomingMessage);
+ } catch (e) {
+ const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
+ runtime.LogDebug(error);
+ throw new Error(error);
+ }
+ let callbackID = message.callbackid;
+ let callbackData = callbacks[callbackID];
+ if (!callbackData) {
+ const error = `Callback '${callbackID}' not registered!!!`;
+ console.error(error);
+ throw new Error(error);
+ }
+ clearTimeout(callbackData.timeoutHandle);
+ delete callbacks[callbackID];
+ if (message.error) {
+ callbackData.reject(message.error);
+ } else {
+ callbackData.resolve(message.result);
+ }
+ }
+
+ // desktop/bindings.js
+ window.go = {};
+ function SetBindings(bindingsMap) {
+ try {
+ bindingsMap = JSON.parse(bindingsMap);
+ } catch (e) {
+ console.error(e);
+ }
+ window.go = window.go || {};
+ Object.keys(bindingsMap).forEach((packageName) => {
+ window.go[packageName] = window.go[packageName] || {};
+ Object.keys(bindingsMap[packageName]).forEach((structName) => {
+ window.go[packageName][structName] = window.go[packageName][structName] || {};
+ Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
+ window.go[packageName][structName][methodName] = function() {
+ let timeout = 0;
+ function dynamic() {
+ const args = [].slice.call(arguments);
+ return Call([packageName, structName, methodName].join("."), args, timeout);
+ }
+ dynamic.setTimeout = function(newTimeout) {
+ timeout = newTimeout;
+ };
+ dynamic.getTimeout = function() {
+ return timeout;
+ };
+ return dynamic;
+ }();
+ });
+ });
+ });
+ }
+
+ // desktop/window.js
+ var window_exports = {};
+ __export(window_exports, {
+ WindowCenter: () => WindowCenter,
+ WindowFullscreen: () => WindowFullscreen,
+ WindowGetPosition: () => WindowGetPosition,
+ WindowGetSize: () => WindowGetSize,
+ WindowHide: () => WindowHide,
+ WindowIsFullscreen: () => WindowIsFullscreen,
+ WindowIsMaximised: () => WindowIsMaximised,
+ WindowIsMinimised: () => WindowIsMinimised,
+ WindowIsNormal: () => WindowIsNormal,
+ WindowMaximise: () => WindowMaximise,
+ WindowMinimise: () => WindowMinimise,
+ WindowReload: () => WindowReload,
+ WindowReloadApp: () => WindowReloadApp,
+ WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop,
+ WindowSetBackgroundColour: () => WindowSetBackgroundColour,
+ WindowSetDarkTheme: () => WindowSetDarkTheme,
+ WindowSetLightTheme: () => WindowSetLightTheme,
+ WindowSetMaxSize: () => WindowSetMaxSize,
+ WindowSetMinSize: () => WindowSetMinSize,
+ WindowSetPosition: () => WindowSetPosition,
+ WindowSetSize: () => WindowSetSize,
+ WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme,
+ WindowSetTitle: () => WindowSetTitle,
+ WindowShow: () => WindowShow,
+ WindowToggleMaximise: () => WindowToggleMaximise,
+ WindowUnfullscreen: () => WindowUnfullscreen,
+ WindowUnmaximise: () => WindowUnmaximise,
+ WindowUnminimise: () => WindowUnminimise
+ });
+ function WindowReload() {
+ window.location.reload();
+ }
+ function WindowReloadApp() {
+ window.WailsInvoke("WR");
+ }
+ function WindowSetSystemDefaultTheme() {
+ window.WailsInvoke("WASDT");
+ }
+ function WindowSetLightTheme() {
+ window.WailsInvoke("WALT");
+ }
+ function WindowSetDarkTheme() {
+ window.WailsInvoke("WADT");
+ }
+ function WindowCenter() {
+ window.WailsInvoke("Wc");
+ }
+ function WindowSetTitle(title) {
+ window.WailsInvoke("WT" + title);
+ }
+ function WindowFullscreen() {
+ window.WailsInvoke("WF");
+ }
+ function WindowUnfullscreen() {
+ window.WailsInvoke("Wf");
+ }
+ function WindowIsFullscreen() {
+ return Call(":wails:WindowIsFullscreen");
+ }
+ function WindowSetSize(width, height) {
+ window.WailsInvoke("Ws:" + width + ":" + height);
+ }
+ function WindowGetSize() {
+ return Call(":wails:WindowGetSize");
+ }
+ function WindowSetMaxSize(width, height) {
+ window.WailsInvoke("WZ:" + width + ":" + height);
+ }
+ function WindowSetMinSize(width, height) {
+ window.WailsInvoke("Wz:" + width + ":" + height);
+ }
+ function WindowSetAlwaysOnTop(b) {
+ window.WailsInvoke("WATP:" + (b ? "1" : "0"));
+ }
+ function WindowSetPosition(x, y) {
+ window.WailsInvoke("Wp:" + x + ":" + y);
+ }
+ function WindowGetPosition() {
+ return Call(":wails:WindowGetPos");
+ }
+ function WindowHide() {
+ window.WailsInvoke("WH");
+ }
+ function WindowShow() {
+ window.WailsInvoke("WS");
+ }
+ function WindowMaximise() {
+ window.WailsInvoke("WM");
+ }
+ function WindowToggleMaximise() {
+ window.WailsInvoke("Wt");
+ }
+ function WindowUnmaximise() {
+ window.WailsInvoke("WU");
+ }
+ function WindowIsMaximised() {
+ return Call(":wails:WindowIsMaximised");
+ }
+ function WindowMinimise() {
+ window.WailsInvoke("Wm");
+ }
+ function WindowUnminimise() {
+ window.WailsInvoke("Wu");
+ }
+ function WindowIsMinimised() {
+ return Call(":wails:WindowIsMinimised");
+ }
+ function WindowIsNormal() {
+ return Call(":wails:WindowIsNormal");
+ }
+ function WindowSetBackgroundColour(R, G, B, A) {
+ let rgba = JSON.stringify({ r: R || 0, g: G || 0, b: B || 0, a: A || 255 });
+ window.WailsInvoke("Wr:" + rgba);
+ }
+
+ // desktop/screen.js
+ var screen_exports = {};
+ __export(screen_exports, {
+ ScreenGetAll: () => ScreenGetAll
+ });
+ function ScreenGetAll() {
+ return Call(":wails:ScreenGetAll");
+ }
+
+ // desktop/browser.js
+ var browser_exports = {};
+ __export(browser_exports, {
+ BrowserOpenURL: () => BrowserOpenURL
+ });
+ function BrowserOpenURL(url) {
+ window.WailsInvoke("BO:" + url);
+ }
+
+ // desktop/clipboard.js
+ var clipboard_exports = {};
+ __export(clipboard_exports, {
+ ClipboardGetText: () => ClipboardGetText,
+ ClipboardSetText: () => ClipboardSetText
+ });
+ function ClipboardSetText(text) {
+ return Call(":wails:ClipboardSetText", [text]);
+ }
+ function ClipboardGetText() {
+ return Call(":wails:ClipboardGetText");
+ }
+
+ // desktop/contextmenu.js
+ function processDefaultContextMenu(event) {
+ const element = event.target;
+ const computedStyle = window.getComputedStyle(element);
+ const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim();
+ switch (defaultContextMenuAction) {
+ case "show":
+ return;
+ case "hide":
+ event.preventDefault();
+ return;
+ default:
+ if (element.isContentEditable) {
+ return;
+ }
+ const selection = window.getSelection();
+ const hasSelection = selection.toString().length > 0;
+ if (hasSelection) {
+ for (let i = 0; i < selection.rangeCount; i++) {
+ const range = selection.getRangeAt(i);
+ const rects = range.getClientRects();
+ for (let j = 0; j < rects.length; j++) {
+ const rect = rects[j];
+ if (document.elementFromPoint(rect.left, rect.top) === element) {
+ return;
+ }
+ }
+ }
+ }
+ if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") {
+ if (hasSelection || !element.readOnly && !element.disabled) {
+ return;
+ }
+ }
+ event.preventDefault();
+ }
+ }
+
+ // desktop/main.js
+ function Quit() {
+ window.WailsInvoke("Q");
+ }
+ function Show() {
+ window.WailsInvoke("S");
+ }
+ function Hide() {
+ window.WailsInvoke("H");
+ }
+ function Environment() {
+ return Call(":wails:Environment");
+ }
+ window.runtime = {
+ ...log_exports,
+ ...window_exports,
+ ...browser_exports,
+ ...screen_exports,
+ ...clipboard_exports,
+ EventsOn,
+ EventsOnce,
+ EventsOnMultiple,
+ EventsEmit,
+ EventsOff,
+ Environment,
+ Show,
+ Hide,
+ Quit
+ };
+ window.wails = {
+ Callback,
+ EventsNotify,
+ SetBindings,
+ eventListeners,
+ callbacks,
+ flags: {
+ disableScrollbarDrag: false,
+ disableDefaultContextMenu: false,
+ enableResize: false,
+ defaultCursor: null,
+ borderThickness: 6,
+ shouldDrag: false,
+ deferDragToMouseMove: true,
+ cssDragProperty: "--wails-draggable",
+ cssDragValue: "drag"
+ }
+ };
+ if (window.wailsbindings) {
+ window.wails.SetBindings(window.wailsbindings);
+ delete window.wails.SetBindings;
+ }
+ if (false) {
+ delete window.wailsbindings;
+ }
+ var dragTest = function(e) {
+ var val = window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);
+ if (val) {
+ val = val.trim();
+ }
+ if (val !== window.wails.flags.cssDragValue) {
+ return false;
+ }
+ if (e.buttons !== 1) {
+ return false;
+ }
+ if (e.detail !== 1) {
+ return false;
+ }
+ return true;
+ };
+ window.wails.setCSSDragProperties = function(property, value) {
+ window.wails.flags.cssDragProperty = property;
+ window.wails.flags.cssDragValue = value;
+ };
+ window.addEventListener("mousedown", (e) => {
+ if (window.wails.flags.resizeEdge) {
+ window.WailsInvoke("resize:" + window.wails.flags.resizeEdge);
+ e.preventDefault();
+ return;
+ }
+ if (dragTest(e)) {
+ if (window.wails.flags.disableScrollbarDrag) {
+ if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
+ return;
+ }
+ }
+ if (window.wails.flags.deferDragToMouseMove) {
+ window.wails.flags.shouldDrag = true;
+ } else {
+ e.preventDefault();
+ window.WailsInvoke("drag");
+ }
+ return;
+ } else {
+ window.wails.flags.shouldDrag = false;
+ }
+ });
+ window.addEventListener("mouseup", () => {
+ window.wails.flags.shouldDrag = false;
+ });
+ function setResize(cursor) {
+ document.documentElement.style.cursor = cursor || window.wails.flags.defaultCursor;
+ window.wails.flags.resizeEdge = cursor;
+ }
+ window.addEventListener("mousemove", function(e) {
+ if (window.wails.flags.shouldDrag) {
+ window.wails.flags.shouldDrag = false;
+ let mousePressed = e.buttons !== void 0 ? e.buttons : e.which;
+ if (mousePressed > 0) {
+ window.WailsInvoke("drag");
+ return;
+ }
+ }
+ if (!window.wails.flags.enableResize) {
+ return;
+ }
+ if (window.wails.flags.defaultCursor == null) {
+ window.wails.flags.defaultCursor = document.documentElement.style.cursor;
+ }
+ if (window.outerWidth - e.clientX < window.wails.flags.borderThickness && window.outerHeight - e.clientY < window.wails.flags.borderThickness) {
+ document.documentElement.style.cursor = "se-resize";
+ }
+ let rightBorder = window.outerWidth - e.clientX < window.wails.flags.borderThickness;
+ let leftBorder = e.clientX < window.wails.flags.borderThickness;
+ let topBorder = e.clientY < window.wails.flags.borderThickness;
+ let bottomBorder = window.outerHeight - e.clientY < window.wails.flags.borderThickness;
+ if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && window.wails.flags.resizeEdge !== void 0) {
+ setResize();
+ } else if (rightBorder && bottomBorder)
+ setResize("se-resize");
+ else if (leftBorder && bottomBorder)
+ setResize("sw-resize");
+ else if (leftBorder && topBorder)
+ setResize("nw-resize");
+ else if (topBorder && rightBorder)
+ setResize("ne-resize");
+ else if (leftBorder)
+ setResize("w-resize");
+ else if (topBorder)
+ setResize("n-resize");
+ else if (bottomBorder)
+ setResize("s-resize");
+ else if (rightBorder)
+ setResize("e-resize");
+ });
+ window.addEventListener("contextmenu", function(e) {
+ if (true)
+ return;
+ if (window.wails.flags.disableDefaultContextMenu) {
+ e.preventDefault();
+ } else {
+ processDefaultContextMenu(e);
+ }
+ });
+ window.WailsInvoke("runtime:ready");
+})();
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2NsaXBib2FyZC5qcyIsICJkZXNrdG9wL2NvbnRleHRtZW51LmpzIiwgImRlc2t0b3AvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLypcbiBfICAgICAgIF9fICAgICAgXyBfX1xufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLyoqXG4gKiBTZW5kcyBhIGxvZyBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kIHdpdGggdGhlIGdpdmVuIGxldmVsICsgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBsZXZlbFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gc2VuZExvZ01lc3NhZ2UobGV2ZWwsIG1lc3NhZ2UpIHtcblxuXHQvLyBMb2cgTWVzc2FnZSBmb3JtYXQ6XG5cdC8vIGxbdHlwZV1bbWVzc2FnZV1cblx0d2luZG93LldhaWxzSW52b2tlKCdMJyArIGxldmVsICsgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB0cmFjZSBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nVHJhY2UobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnVCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1ByaW50KG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1AnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGRlYnVnIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dEZWJ1ZyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdEJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBpbmZvIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dJbmZvKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ0knLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIHdhcm5pbmcgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1dhcm5pbmcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnVycsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gZXJyb3IgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ0Vycm9yKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ0UnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGZhdGFsIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dGYXRhbChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdGJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgTG9nIGxldmVsIHRvIHRoZSBnaXZlbiBsb2cgbGV2ZWxcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gbG9nbGV2ZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldExvZ0xldmVsKGxvZ2xldmVsKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdTJywgbG9nbGV2ZWwpO1xufVxuXG4vLyBMb2cgbGV2ZWxzXG5leHBvcnQgY29uc3QgTG9nTGV2ZWwgPSB7XG5cdFRSQUNFOiAxLFxuXHRERUJVRzogMixcblx0SU5GTzogMyxcblx0V0FSTklORzogNCxcblx0RVJST1I6IDUsXG59O1xuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG4vLyBEZWZpbmVzIGEgc2luZ2xlIGxpc3RlbmVyIHdpdGggYSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyB0byBjYWxsYmFja1xuXG4vKipcbiAqIFRoZSBMaXN0ZW5lciBjbGFzcyBkZWZpbmVzIGEgbGlzdGVuZXIhIDotKVxuICpcbiAqIEBjbGFzcyBMaXN0ZW5lclxuICovXG5jbGFzcyBMaXN0ZW5lciB7XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBMaXN0ZW5lci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzXG4gICAgICogQG1lbWJlcm9mIExpc3RlbmVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xuICAgICAgICAvLyBEZWZhdWx0IG9mIC0xIG1lYW5zIGluZmluaXRlXG4gICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzID0gbWF4Q2FsbGJhY2tzIHx8IC0xO1xuICAgICAgICAvLyBDYWxsYmFjayBpbnZva2VzIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBnaXZlbiBkYXRhXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiB0aGlzIGxpc3RlbmVyIHNob3VsZCBiZSBkZXN0cm95ZWRcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBkYXRhKTtcbiAgICAgICAgICAgIC8vIElmIG1heENhbGxiYWNrcyBpcyBpbmZpbml0ZSwgcmV0dXJuIGZhbHNlIChkbyBub3QgZGVzdHJveSlcbiAgICAgICAgICAgIGlmICh0aGlzLm1heENhbGxiYWNrcyA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEZWNyZW1lbnQgbWF4Q2FsbGJhY2tzLiBSZXR1cm4gdHJ1ZSBpZiBub3cgMCwgb3RoZXJ3aXNlIGZhbHNlXG4gICAgICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF4Q2FsbGJhY2tzID09PSAwO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZXhwb3J0IGNvbnN0IGV2ZW50TGlzdGVuZXJzID0ge307XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGBtYXhDYWxsYmFja3NgIHRpbWVzIGJlZm9yZSBiZWluZyBkZXN0cm95ZWRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcyk7XG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5wdXNoKHRoaXNMaXN0ZW5lcik7XG4gICAgcmV0dXJuICgpID0+IGxpc3RlbmVyT2ZmKHRoaXNMaXN0ZW5lcik7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGV2ZXJ5IHRpbWUgdGhlIGV2ZW50IGlzIGVtaXR0ZWRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIG9uY2UgdGhlbiBkZXN0cm95ZWRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uY2UoZXZlbnROYW1lLCBjYWxsYmFjaykge1xuICAgIHJldHVybiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xufVxuXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XG5cbiAgICAvLyBHZXQgdGhlIGV2ZW50IG5hbWVcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XG5cbiAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGFueSBsaXN0ZW5lcnMgZm9yIHRoaXMgZXZlbnRcbiAgICBpZiAoZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xuXG4gICAgICAgIC8vIEtlZXAgYSBsaXN0IG9mIGxpc3RlbmVyIGluZGV4ZXMgdG8gZGVzdHJveVxuICAgICAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uc2xpY2UoKTtcblxuICAgICAgICAvLyBJdGVyYXRlIGxpc3RlbmVyc1xuICAgICAgICBmb3IgKGxldCBjb3VudCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoIC0gMTsgY291bnQgPj0gMDsgY291bnQgLT0gMSkge1xuXG4gICAgICAgICAgICAvLyBHZXQgbmV4dCBsaXN0ZW5lclxuICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdW2NvdW50XTtcblxuICAgICAgICAgICAgbGV0IGRhdGEgPSBldmVudERhdGEuZGF0YTtcblxuICAgICAgICAgICAgLy8gRG8gdGhlIGNhbGxiYWNrXG4gICAgICAgICAgICBjb25zdCBkZXN0cm95ID0gbGlzdGVuZXIuQ2FsbGJhY2soZGF0YSk7XG4gICAgICAgICAgICBpZiAoZGVzdHJveSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBsaXN0ZW5lciBpbmRpY2F0ZWQgdG8gZGVzdHJveSBpdHNlbGYsIGFkZCBpdCB0byB0aGUgZGVzdHJveSBsaXN0XG4gICAgICAgICAgICAgICAgbmV3RXZlbnRMaXN0ZW5lckxpc3Quc3BsaWNlKGNvdW50LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSBjYWxsYmFja3Mgd2l0aCBuZXcgbGlzdCBvZiBsaXN0ZW5lcnNcbiAgICAgICAgaWYgKG5ld0V2ZW50TGlzdGVuZXJMaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBuZXdFdmVudExpc3RlbmVyTGlzdDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBOb3RpZnkgaW5mb3JtcyBmcm9udGVuZCBsaXN0ZW5lcnMgdGhhdCBhbiBldmVudCB3YXMgZW1pdHRlZCB3aXRoIHRoZSBnaXZlbiBkYXRhXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG5vdGlmeU1lc3NhZ2UgLSBlbmNvZGVkIG5vdGlmaWNhdGlvbiBtZXNzYWdlXG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c05vdGlmeShub3RpZnlNZXNzYWdlKSB7XG4gICAgLy8gUGFyc2UgdGhlIG1lc3NhZ2VcbiAgICBsZXQgbWVzc2FnZTtcbiAgICB0cnkge1xuICAgICAgICBtZXNzYWdlID0gSlNPTi5wYXJzZShub3RpZnlNZXNzYWdlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IGVycm9yID0gJ0ludmFsaWQgSlNPTiBwYXNzZWQgdG8gTm90aWZ5OiAnICsgbm90aWZ5TWVzc2FnZTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yKTtcbiAgICB9XG4gICAgbm90aWZ5TGlzdGVuZXJzKG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIEVtaXQgYW4gZXZlbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgZGF0YVxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c0VtaXQoZXZlbnROYW1lKSB7XG5cbiAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICBuYW1lOiBldmVudE5hbWUsXG4gICAgICAgIGRhdGE6IFtdLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykuc2xpY2UoMSksXG4gICAgfTtcblxuICAgIC8vIE5vdGlmeSBKUyBsaXN0ZW5lcnNcbiAgICBub3RpZnlMaXN0ZW5lcnMocGF5bG9hZCk7XG5cbiAgICAvLyBOb3RpZnkgR28gbGlzdGVuZXJzXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFRScgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSkge1xuICAgIC8vIFJlbW92ZSBsb2NhbCBsaXN0ZW5lcnNcbiAgICBkZWxldGUgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VYJyArIGV2ZW50TmFtZSk7XG59XG5cbi8qKlxuICogT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggT24sXG4gKiBvcHRpb25hbGx5IG11bHRpcGxlIGxpc3RlbmVyZXMgY2FuIGJlIHVucmVnaXN0ZXJlZCB2aWEgYGFkZGl0aW9uYWxFdmVudE5hbWVzYFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSAgey4uLnN0cmluZ30gYWRkaXRpb25hbEV2ZW50TmFtZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XG4gICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKVxuXG4gICAgaWYgKGFkZGl0aW9uYWxFdmVudE5hbWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYWRkaXRpb25hbEV2ZW50TmFtZXMuZm9yRWFjaChldmVudE5hbWUgPT4ge1xuICAgICAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKVxuICAgICAgICB9KVxuICAgIH1cbn1cblxuLyoqXG4gKiBPZmYgdW5yZWdpc3RlcnMgYWxsIGV2ZW50IGxpc3RlbmVycyBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBPblxuICovXG4gZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09mZkFsbCgpIHtcbiAgICBjb25zdCBldmVudE5hbWVzID0gT2JqZWN0LmtleXMoZXZlbnRMaXN0ZW5lcnMpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpICE9PSBldmVudE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZXNbaV0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBsaXN0ZW5lck9mZiB1bnJlZ2lzdGVycyBhIGxpc3RlbmVyIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIEV2ZW50c09uXG4gKlxuICogQHBhcmFtIHtMaXN0ZW5lcn0gbGlzdGVuZXJcbiAqL1xuIGZ1bmN0aW9uIGxpc3RlbmVyT2ZmKGxpc3RlbmVyKSB7XG4gICAgY29uc3QgZXZlbnROYW1lID0gbGlzdGVuZXIuZXZlbnROYW1lO1xuICAgIC8vIFJlbW92ZSBsb2NhbCBsaXN0ZW5lclxuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmZpbHRlcihsID0+IGwgIT09IGxpc3RlbmVyKTtcblxuICAgIC8vIENsZWFuIHVwIGlmIHRoZXJlIGFyZSBubyBldmVudCBsaXN0ZW5lcnMgbGVmdFxuICAgIGlmIChldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpO1xuICAgIH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuZXhwb3J0IGNvbnN0IGNhbGxiYWNrcyA9IHt9O1xuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgZnJvbSB0aGUgbmF0aXZlIGJyb3dzZXIgcmFuZG9tIGZ1bmN0aW9uXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGNyeXB0b1JhbmRvbSgpIHtcblx0dmFyIGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KDEpO1xuXHRyZXR1cm4gd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpWzBdO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgdXNpbmcgZGEgb2xkLXNrb29sIE1hdGguUmFuZG9tXG4gKiBJIGxpa2VzIHRvIGNhbGwgaXQgTE9MUmFuZG9tXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGJhc2ljUmFuZG9tKCkge1xuXHRyZXR1cm4gTWF0aC5yYW5kb20oKSAqIDkwMDcxOTkyNTQ3NDA5OTE7XG59XG5cbi8vIFBpY2sgYSByYW5kb20gbnVtYmVyIGZ1bmN0aW9uIGJhc2VkIG9uIGJyb3dzZXIgY2FwYWJpbGl0eVxudmFyIHJhbmRvbUZ1bmM7XG5pZiAod2luZG93LmNyeXB0bykge1xuXHRyYW5kb21GdW5jID0gY3J5cHRvUmFuZG9tO1xufSBlbHNlIHtcblx0cmFuZG9tRnVuYyA9IGJhc2ljUmFuZG9tO1xufVxuXG5cbi8qKlxuICogQ2FsbCBzZW5kcyBhIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgdG8gY2FsbCB0aGUgYmluZGluZyB3aXRoIHRoZVxuICogZ2l2ZW4gZGF0YS4gQSBwcm9taXNlIGlzIHJldHVybmVkIGFuZCB3aWxsIGJlIGNvbXBsZXRlZCB3aGVuIHRoZVxuICogYmFja2VuZCByZXNwb25kcy4gVGhpcyB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGNhbGwgd2FzIHN1Y2Nlc3NmdWxcbiAqIG9yIHJlamVjdGVkIGlmIGFuIGVycm9yIGlzIHBhc3NlZCBiYWNrLlxuICogVGhlcmUgaXMgYSB0aW1lb3V0IG1lY2hhbmlzbS4gSWYgdGhlIGNhbGwgZG9lc24ndCByZXNwb25kIGluIHRoZSBnaXZlblxuICogdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0aGVuIHRoZSBwcm9taXNlIGlzIHJlamVjdGVkLlxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge2FueT19IGFyZ3NcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xuXG5cdC8vIFRpbWVvdXQgaW5maW5pdGUgYnkgZGVmYXVsdFxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XG5cdFx0dGltZW91dCA9IDA7XG5cdH1cblxuXHQvLyBDcmVhdGUgYSBwcm9taXNlXG5cdHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG5cblx0XHQvLyBDcmVhdGUgYSB1bmlxdWUgY2FsbGJhY2tJRFxuXHRcdHZhciBjYWxsYmFja0lEO1xuXHRcdGRvIHtcblx0XHRcdGNhbGxiYWNrSUQgPSBuYW1lICsgJy0nICsgcmFuZG9tRnVuYygpO1xuXHRcdH0gd2hpbGUgKGNhbGxiYWNrc1tjYWxsYmFja0lEXSk7XG5cblx0XHR2YXIgdGltZW91dEhhbmRsZTtcblx0XHQvLyBTZXQgdGltZW91dFxuXHRcdGlmICh0aW1lb3V0ID4gMCkge1xuXHRcdFx0dGltZW91dEhhbmRsZSA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRyZWplY3QoRXJyb3IoJ0NhbGwgdG8gJyArIG5hbWUgKyAnIHRpbWVkIG91dC4gUmVxdWVzdCBJRDogJyArIGNhbGxiYWNrSUQpKTtcblx0XHRcdH0sIHRpbWVvdXQpO1xuXHRcdH1cblxuXHRcdC8vIFN0b3JlIGNhbGxiYWNrXG5cdFx0Y2FsbGJhY2tzW2NhbGxiYWNrSURdID0ge1xuXHRcdFx0dGltZW91dEhhbmRsZTogdGltZW91dEhhbmRsZSxcblx0XHRcdHJlamVjdDogcmVqZWN0LFxuXHRcdFx0cmVzb2x2ZTogcmVzb2x2ZVxuXHRcdH07XG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgcGF5bG9hZCA9IHtcblx0XHRcdFx0bmFtZSxcblx0XHRcdFx0YXJncyxcblx0XHRcdFx0Y2FsbGJhY2tJRCxcblx0XHRcdH07XG5cbiAgICAgICAgICAgIC8vIE1ha2UgdGhlIGNhbGxcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnQycgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG53aW5kb3cuT2JmdXNjYXRlZENhbGwgPSAoaWQsIGFyZ3MsIHRpbWVvdXQpID0+IHtcblxuICAgIC8vIFRpbWVvdXQgaW5maW5pdGUgYnkgZGVmYXVsdFxuICAgIGlmICh0aW1lb3V0ID09IG51bGwpIHtcbiAgICAgICAgdGltZW91dCA9IDA7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIGEgcHJvbWlzZVxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcbiAgICAgICAgdmFyIGNhbGxiYWNrSUQ7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIGNhbGxiYWNrSUQgPSBpZCArICctJyArIHJhbmRvbUZ1bmMoKTtcbiAgICAgICAgfSB3aGlsZSAoY2FsbGJhY2tzW2NhbGxiYWNrSURdKTtcblxuICAgICAgICB2YXIgdGltZW91dEhhbmRsZTtcbiAgICAgICAgLy8gU2V0IHRpbWVvdXRcbiAgICAgICAgaWYgKHRpbWVvdXQgPiAwKSB7XG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdDYWxsIHRvIG1ldGhvZCAnICsgaWQgKyAnIHRpbWVkIG91dC4gUmVxdWVzdCBJRDogJyArIGNhbGxiYWNrSUQpKTtcbiAgICAgICAgICAgIH0sIHRpbWVvdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RvcmUgY2FsbGJhY2tcbiAgICAgICAgY2FsbGJhY2tzW2NhbGxiYWNrSURdID0ge1xuICAgICAgICAgICAgdGltZW91dEhhbmRsZTogdGltZW91dEhhbmRsZSxcbiAgICAgICAgICAgIHJlamVjdDogcmVqZWN0LFxuICAgICAgICAgICAgcmVzb2x2ZTogcmVzb2x2ZVxuICAgICAgICB9O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0ge1xuXHRcdFx0XHRpZCxcblx0XHRcdFx0YXJncyxcblx0XHRcdFx0Y2FsbGJhY2tJRCxcblx0XHRcdH07XG5cbiAgICAgICAgICAgIC8vIE1ha2UgdGhlIGNhbGxcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnYycgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuXG4vKipcbiAqIENhbGxlZCBieSB0aGUgYmFja2VuZCB0byByZXR1cm4gZGF0YSB0byBhIHByZXZpb3VzbHkgY2FsbGVkXG4gKiBiaW5kaW5nIGludm9jYXRpb25cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gaW5jb21pbmdNZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYWxsYmFjayhpbmNvbWluZ01lc3NhZ2UpIHtcblx0Ly8gUGFyc2UgdGhlIG1lc3NhZ2Vcblx0bGV0IG1lc3NhZ2U7XG5cdHRyeSB7XG5cdFx0bWVzc2FnZSA9IEpTT04ucGFyc2UoaW5jb21pbmdNZXNzYWdlKTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdGNvbnN0IGVycm9yID0gYEludmFsaWQgSlNPTiBwYXNzZWQgdG8gY2FsbGJhY2s6ICR7ZS5tZXNzYWdlfS4gTWVzc2FnZTogJHtpbmNvbWluZ01lc3NhZ2V9YDtcblx0XHRydW50aW1lLkxvZ0RlYnVnKGVycm9yKTtcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHR9XG5cdGxldCBjYWxsYmFja0lEID0gbWVzc2FnZS5jYWxsYmFja2lkO1xuXHRsZXQgY2FsbGJhY2tEYXRhID0gY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXHRpZiAoIWNhbGxiYWNrRGF0YSkge1xuXHRcdGNvbnN0IGVycm9yID0gYENhbGxiYWNrICcke2NhbGxiYWNrSUR9JyBub3QgcmVnaXN0ZXJlZCEhIWA7XG5cdFx0Y29uc29sZS5lcnJvcihlcnJvcik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHR9XG5cdGNsZWFyVGltZW91dChjYWxsYmFja0RhdGEudGltZW91dEhhbmRsZSk7XG5cblx0ZGVsZXRlIGNhbGxiYWNrc1tjYWxsYmFja0lEXTtcblxuXHRpZiAobWVzc2FnZS5lcnJvcikge1xuXHRcdGNhbGxiYWNrRGF0YS5yZWplY3QobWVzc2FnZS5lcnJvcik7XG5cdH0gZWxzZSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlc29sdmUobWVzc2FnZS5yZXN1bHQpO1xuXHR9XG59XG4iLCAiLypcbiBfICAgICAgIF9fICAgICAgXyBfXyAgICBcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKSBcbnxfXy98X18vXFxfXyxfL18vXy9fX19fLyAgXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG5pbXBvcnQge0NhbGx9IGZyb20gJy4vY2FsbHMnO1xuXG4vLyBUaGlzIGlzIHdoZXJlIHdlIGJpbmQgZ28gbWV0aG9kIHdyYXBwZXJzXG53aW5kb3cuZ28gPSB7fTtcblxuZXhwb3J0IGZ1bmN0aW9uIFNldEJpbmRpbmdzKGJpbmRpbmdzTWFwKSB7XG5cdHRyeSB7XG5cdFx0YmluZGluZ3NNYXAgPSBKU09OLnBhcnNlKGJpbmRpbmdzTWFwKTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdGNvbnNvbGUuZXJyb3IoZSk7XG5cdH1cblxuXHQvLyBJbml0aWFsaXNlIHRoZSBiaW5kaW5ncyBtYXBcblx0d2luZG93LmdvID0gd2luZG93LmdvIHx8IHt9O1xuXG5cdC8vIEl0ZXJhdGUgcGFja2FnZSBuYW1lc1xuXHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcCkuZm9yRWFjaCgocGFja2FnZU5hbWUpID0+IHtcblxuXHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxuXHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdIHx8IHt9O1xuXG5cdFx0Ly8gSXRlcmF0ZSBzdHJ1Y3QgbmFtZXNcblx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV0pLmZvckVhY2goKHN0cnVjdE5hbWUpID0+IHtcblxuXHRcdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XG5cdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcblxuXHRcdFx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXBbcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdKS5mb3JFYWNoKChtZXRob2ROYW1lKSA9PiB7XG5cblx0XHRcdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uICgpIHtcblxuXHRcdFx0XHRcdC8vIE5vIHRpbWVvdXQgYnkgZGVmYXVsdFxuXHRcdFx0XHRcdGxldCB0aW1lb3V0ID0gMDtcblxuXHRcdFx0XHRcdC8vIEFjdHVhbCBmdW5jdGlvblxuXHRcdFx0XHRcdGZ1bmN0aW9uIGR5bmFtaWMoKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIENhbGwoW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXS5qb2luKCcuJyksIGFyZ3MsIHRpbWVvdXQpO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIEFsbG93IHNldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxuXHRcdFx0XHRcdGR5bmFtaWMuc2V0VGltZW91dCA9IGZ1bmN0aW9uIChuZXdUaW1lb3V0KSB7XG5cdFx0XHRcdFx0XHR0aW1lb3V0ID0gbmV3VGltZW91dDtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0Ly8gQWxsb3cgZ2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZHluYW1pYy5nZXRUaW1lb3V0ID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRpbWVvdXQ7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdHJldHVybiBkeW5hbWljO1xuXHRcdFx0XHR9KCk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fSk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dSZWxvYWQoKSB7XG4gICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkQXBwKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1InKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFN5c3RlbURlZmF1bHRUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBU0RUJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRMaWdodFRoZW1lKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FMVCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0RGFya1RoZW1lKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FEVCcpO1xufVxuXG4vKipcbiAqIFBsYWNlIHRoZSB3aW5kb3cgaW4gdGhlIGNlbnRlciBvZiB0aGUgc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93Q2VudGVyKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2MnKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdGl0bGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFRpdGxlKHRpdGxlKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXVCcgKyB0aXRsZSk7XG59XG5cbi8qKlxuICogTWFrZXMgdGhlIHdpbmRvdyBnbyBmdWxsc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93RnVsbHNjcmVlbigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dGJyk7XG59XG5cbi8qKlxuICogUmV2ZXJ0cyB0aGUgd2luZG93IGZyb20gZnVsbHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VuZnVsbHNjcmVlbigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dmJyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgaW4gZnVsbCBzY3JlZW4gbW9kZSBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzRnVsbHNjcmVlbigpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc0Z1bGxzY3JlZW5cIik7XG59XG5cbi8qKlxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3M6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8e3c6IG51bWJlciwgaDogbnVtYmVyfT59IFRoZSBzaXplIG9mIHRoZSB3aW5kb3dcblxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93R2V0U2l6ZSgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRTaXplXCIpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgbWF4aW11bSBzaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d6OicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cblxuXG4vKipcbiAqIFNldCB0aGUgd2luZG93IEFsd2F5c09uVG9wIG9yIG5vdCBvbiB0b3BcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRBbHdheXNPblRvcChiKSB7XG5cbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBVFA6JyArIChiID8gJzEnIDogJzAnKSk7XG59XG5cblxuXG5cbi8qKlxuICogU2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRQb3NpdGlvbih4LCB5KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcDonICsgeCArICc6JyArIHkpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8e3g6IG51bWJlciwgeTogbnVtYmVyfT59IFRoZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRQb3NpdGlvbigpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRQb3NcIik7XG59XG5cbi8qKlxuICogSGlkZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SGlkZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dIJyk7XG59XG5cbi8qKlxuICogU2hvdyB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2hvdygpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dTJyk7XG59XG5cbi8qKlxuICogTWF4aW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV00nKTtcbn1cblxuLyoqXG4gKiBUb2dnbGUgdGhlIE1heGltaXNlIG9mIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dUb2dnbGVNYXhpbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d0Jyk7XG59XG5cbi8qKlxuICogVW5tYXhpbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5tYXhpbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dVJyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbWF4aW1pc2VkIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNYXhpbWlzZWQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNNYXhpbWlzZWRcIik7XG59XG5cbi8qKlxuICogTWluaW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01pbmltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV20nKTtcbn1cblxuLyoqXG4gKiBVbm1pbmltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbm1pbmltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3UnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBtaW5pbWlzZWQgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc01pbmltaXNlZCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc01pbmltaXNlZFwiKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBub3JtYWwgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc05vcm1hbCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc05vcm1hbFwiKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IFIgUmVkXG4gKiBAcGFyYW0ge251bWJlcn0gRyBHcmVlblxuICogQHBhcmFtIHtudW1iZXJ9IEIgQmx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IEEgQWxwaGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldEJhY2tncm91bmRDb2xvdXIoUiwgRywgQiwgQSkge1xuICAgIGxldCByZ2JhID0gSlNPTi5zdHJpbmdpZnkoe3I6IFIgfHwgMCwgZzogRyB8fCAwLCBiOiBCIHx8IDAsIGE6IEEgfHwgMjU1fSk7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcjonICsgcmdiYSk7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcblxuXG4vKipcbiAqIEdldHMgdGhlIGFsbCBzY3JlZW5zLiBDYWxsIHRoaXMgYW5ldyBlYWNoIHRpbWUgeW91IHdhbnQgdG8gcmVmcmVzaCBkYXRhIGZyb20gdGhlIHVuZGVybHlpbmcgd2luZG93aW5nIHN5c3RlbS5cbiAqIEBleHBvcnRcbiAqIEB0eXBlZGVmIHtpbXBvcnQoJy4uL3dyYXBwZXIvcnVudGltZScpLlNjcmVlbn0gU2NyZWVuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHtTY3JlZW5bXX0+fSBUaGUgc2NyZWVuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gU2NyZWVuR2V0QWxsKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOlNjcmVlbkdldEFsbFwiKTtcbn1cbiIsICIvKipcbiAqIEBkZXNjcmlwdGlvbjogVXNlIHRoZSBzeXN0ZW0gZGVmYXVsdCBicm93c2VyIHRvIG9wZW4gdGhlIHVybFxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBCcm93c2VyT3BlblVSTCh1cmwpIHtcbiAgd2luZG93LldhaWxzSW52b2tlKCdCTzonICsgdXJsKTtcbn0iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG4vKipcbiAqIFNldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IHRleHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsaXBib2FyZFNldFRleHQodGV4dCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOkNsaXBib2FyZFNldFRleHRcIiwgW3RleHRdKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHRleHQgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7c3RyaW5nfT59IFRleHQgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkXG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsaXBib2FyZEdldFRleHQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6Q2xpcGJvYXJkR2V0VGV4dFwiKTtcbn0iLCAiLypcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogYXV0bzsgKGRlZmF1bHQpIHdpbGwgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnUgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWUgT1IgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBPUiBlbGVtZW50IGlzIGlucHV0IG9yIHRleHRhcmVhXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IHNob3c7IHdpbGwgYWx3YXlzIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGhpZGU7IHdpbGwgYWx3YXlzIGhpZGUgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XG5cblRoaXMgcnVsZSBpcyBpbmhlcml0ZWQgbGlrZSBub3JtYWwgQ1NTIHJ1bGVzLCBzbyBuZXN0aW5nIHdvcmtzIGFzIGV4cGVjdGVkXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcbiAgICAvLyBQcm9jZXNzIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgY29uc3QgZWxlbWVudCA9IGV2ZW50LnRhcmdldDtcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgY29uc3QgZGVmYXVsdENvbnRleHRNZW51QWN0aW9uID0gY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1kZWZhdWx0LWNvbnRleHRtZW51XCIpLnRyaW0oKTtcbiAgICBzd2l0Y2ggKGRlZmF1bHRDb250ZXh0TWVudUFjdGlvbikge1xuICAgICAgICBjYXNlIFwic2hvd1wiOlxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjYXNlIFwiaGlkZVwiOlxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXG4gICAgICAgICAgICBpZiAoZWxlbWVudC5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBhbmQgYWN0aW9uIGlzIG9uIHRoZSBzZWxlY3RlZCBlbGVtZW50c1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgY29uc3QgaGFzU2VsZWN0aW9uID0gKHNlbGVjdGlvbi50b1N0cmluZygpLmxlbmd0aCA+IDApXG4gICAgICAgICAgICBpZiAoaGFzU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ucmFuZ2VDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhbmdlID0gc2VsZWN0aW9uLmdldFJhbmdlQXQoaSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3RzID0gcmFuZ2UuZ2V0Q2xpZW50UmVjdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZWN0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IHJlY3RzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQocmVjdC5sZWZ0LCByZWN0LnRvcCkgPT09IGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0YWduYW1lIGlzIGlucHV0IG9yIHRleHRhcmVhXG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSBcIklOUFVUXCIgfHwgZWxlbWVudC50YWdOYW1lID09PSBcIlRFWFRBUkVBXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzU2VsZWN0aW9uIHx8ICghZWxlbWVudC5yZWFkT25seSAmJiAhZWxlbWVudC5kaXNhYmxlZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xuaW1wb3J0IHtldmVudExpc3RlbmVycywgRXZlbnRzRW1pdCwgRXZlbnRzTm90aWZ5LCBFdmVudHNPZmYsIEV2ZW50c09uLCBFdmVudHNPbmNlLCBFdmVudHNPbk11bHRpcGxlfSBmcm9tICcuL2V2ZW50cyc7XG5pbXBvcnQge0NhbGwsIENhbGxiYWNrLCBjYWxsYmFja3N9IGZyb20gJy4vY2FsbHMnO1xuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcbmltcG9ydCAqIGFzIFdpbmRvdyBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCAqIGFzIFNjcmVlbiBmcm9tIFwiLi9zY3JlZW5cIjtcbmltcG9ydCAqIGFzIEJyb3dzZXIgZnJvbSBcIi4vYnJvd3NlclwiO1xuaW1wb3J0ICogYXMgQ2xpcGJvYXJkIGZyb20gXCIuL2NsaXBib2FyZFwiO1xuaW1wb3J0ICogYXMgQ29udGV4dE1lbnUgZnJvbSBcIi4vY29udGV4dG1lbnVcIjtcblxuXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdTJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnSCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XG59XG5cbi8vIFRoZSBKUyBydW50aW1lXG53aW5kb3cucnVudGltZSA9IHtcbiAgICAuLi5Mb2csXG4gICAgLi4uV2luZG93LFxuICAgIC4uLkJyb3dzZXIsXG4gICAgLi4uU2NyZWVuLFxuICAgIC4uLkNsaXBib2FyZCxcbiAgICBFdmVudHNPbixcbiAgICBFdmVudHNPbmNlLFxuICAgIEV2ZW50c09uTXVsdGlwbGUsXG4gICAgRXZlbnRzRW1pdCxcbiAgICBFdmVudHNPZmYsXG4gICAgRW52aXJvbm1lbnQsXG4gICAgU2hvdyxcbiAgICBIaWRlLFxuICAgIFF1aXRcbn07XG5cbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xud2luZG93LndhaWxzID0ge1xuICAgIENhbGxiYWNrLFxuICAgIEV2ZW50c05vdGlmeSxcbiAgICBTZXRCaW5kaW5ncyxcbiAgICBldmVudExpc3RlbmVycyxcbiAgICBjYWxsYmFja3MsXG4gICAgZmxhZ3M6IHtcbiAgICAgICAgZGlzYWJsZVNjcm9sbGJhckRyYWc6IGZhbHNlLFxuICAgICAgICBkaXNhYmxlRGVmYXVsdENvbnRleHRNZW51OiBmYWxzZSxcbiAgICAgICAgZW5hYmxlUmVzaXplOiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdEN1cnNvcjogbnVsbCxcbiAgICAgICAgYm9yZGVyVGhpY2tuZXNzOiA2LFxuICAgICAgICBzaG91bGREcmFnOiBmYWxzZSxcbiAgICAgICAgZGVmZXJEcmFnVG9Nb3VzZU1vdmU6IHRydWUsXG4gICAgICAgIGNzc0RyYWdQcm9wZXJ0eTogXCItLXdhaWxzLWRyYWdnYWJsZVwiLFxuICAgICAgICBjc3NEcmFnVmFsdWU6IFwiZHJhZ1wiLFxuICAgIH1cbn07XG5cbi8vIFNldCB0aGUgYmluZGluZ3NcbmlmICh3aW5kb3cud2FpbHNiaW5kaW5ncykge1xuICAgIHdpbmRvdy53YWlscy5TZXRCaW5kaW5ncyh3aW5kb3cud2FpbHNiaW5kaW5ncyk7XG4gICAgZGVsZXRlIHdpbmRvdy53YWlscy5TZXRCaW5kaW5ncztcbn1cblxuLy8gKGJvb2wpIFRoaXMgaXMgZXZhbHVhdGVkIGF0IGJ1aWxkIHRpbWUgaW4gcGFja2FnZS5qc29uXG5pZiAoIURFQlVHKSB7XG4gICAgZGVsZXRlIHdpbmRvdy53YWlsc2JpbmRpbmdzO1xufVxuXG5sZXQgZHJhZ1Rlc3QgPSBmdW5jdGlvbiAoZSkge1xuICAgIHZhciB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZSh3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5KTtcbiAgICBpZiAodmFsKSB7XG4gICAgICB2YWwgPSB2YWwudHJpbSgpO1xuICAgIH1cbiAgICBcbiAgICBpZiAodmFsICE9PSB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS5idXR0b25zICE9PSAxKSB7XG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBub3QgdGhlIHByaW1hcnkgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWQuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS5kZXRhaWwgIT09IDEpIHtcbiAgICAgICAgLy8gRG8gbm90IHN0YXJ0IGRyYWdnaW5nIGlmIG1vcmUgdGhhbiBvbmNlIGhhcyBiZWVuIGNsaWNrZWQsIGUuZy4gd2hlbiBkb3VibGUgY2xpY2tpbmdcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxud2luZG93LndhaWxzLnNldENTU0RyYWdQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgIHdpbmRvdy53YWlscy5mbGFncy5jc3NEcmFnUHJvcGVydHkgPSBwcm9wZXJ0eTtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlID0gdmFsdWU7XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4ge1xuXG4gICAgLy8gQ2hlY2sgZm9yIHJlc2l6aW5nXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKSB7XG4gICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcInJlc2l6ZTpcIiArIHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRyYWdUZXN0KGUpKSB7XG4gICAgICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGlzYWJsZVNjcm9sbGJhckRyYWcpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgY2hlY2tzIGZvciBjbGlja3Mgb24gdGhlIHNjcm9sbCBiYXJcbiAgICAgICAgICAgIGlmIChlLm9mZnNldFggPiBlLnRhcmdldC5jbGllbnRXaWR0aCB8fCBlLm9mZnNldFkgPiBlLnRhcmdldC5jbGllbnRIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kZWZlckRyYWdUb01vdXNlTW92ZSkge1xuICAgICAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoXCJkcmFnXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xuICAgIH1cbn0pO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsICgpID0+IHtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xufSk7XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IpIHtcbiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yID0gY3Vyc29yIHx8IHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yO1xuICAgIHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlID0gY3Vyc29yO1xufVxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcpIHtcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSBmYWxzZTtcbiAgICAgICAgbGV0IG1vdXNlUHJlc3NlZCA9IGUuYnV0dG9ucyAhPT0gdW5kZWZpbmVkID8gZS5idXR0b25zIDogZS53aGljaDtcbiAgICAgICAgaWYgKG1vdXNlUHJlc3NlZCA+IDApIHtcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF3aW5kb3cud2FpbHMuZmxhZ3MuZW5hYmxlUmVzaXplKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yID09IG51bGwpIHtcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yO1xuICAgIH1cbiAgICBpZiAod2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzICYmIHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3MpIHtcbiAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IFwic2UtcmVzaXplXCI7XG4gICAgfVxuICAgIGxldCByaWdodEJvcmRlciA9IHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcbiAgICBsZXQgbGVmdEJvcmRlciA9IGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG4gICAgbGV0IGJvdHRvbUJvcmRlciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgc2V0UmVzaXplKCk7XG4gICAgfSBlbHNlIGlmIChyaWdodEJvcmRlciAmJiBib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInNlLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyICYmIGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwic3ctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgdG9wQm9yZGVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQm9yZGVyICYmIHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJuZS1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdEJvcmRlcikgc2V0UmVzaXplKFwidy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInMtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJlLXJlc2l6ZVwiKTtcblxufSk7XG5cbi8vIFNldHVwIGNvbnRleHQgbWVudSBob29rXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbiAoZSkge1xuICAgIC8vIGFsd2F5cyBzaG93IHRoZSBjb250ZXh0bWVudSBpbiBkZWJ1ZyAmIGRldlxuICAgIGlmIChERUJVRykgcmV0dXJuO1xuXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlRGVmYXVsdENvbnRleHRNZW51KSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBDb250ZXh0TWVudS5wcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGUpO1xuICAgIH1cbn0pO1xuXG53aW5kb3cuV2FpbHNJbnZva2UoXCJydW50aW1lOnJlYWR5XCIpOyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBa0JBLFdBQVMsZUFBZSxPQUFPLFNBQVM7QUFJdkMsV0FBTyxZQUFZLE1BQU0sUUFBUSxPQUFPO0FBQUEsRUFDekM7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxTQUFTLFNBQVM7QUFDakMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFFBQVEsU0FBUztBQUNoQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsV0FBVyxTQUFTO0FBQ25DLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxTQUFTLFNBQVM7QUFDakMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsWUFBWSxVQUFVO0FBQ3JDLG1CQUFlLEtBQUssUUFBUTtBQUFBLEVBQzdCO0FBR08sTUFBTSxXQUFXO0FBQUEsSUFDdkIsT0FBTztBQUFBLElBQ1AsT0FBTztBQUFBLElBQ1AsTUFBTTtBQUFBLElBQ04sU0FBUztBQUFBLElBQ1QsT0FBTztBQUFBLEVBQ1I7OztBQzlGQSxNQUFNLFdBQU4sTUFBZTtBQUFBLElBUVgsWUFBWSxXQUFXLFVBQVUsY0FBYztBQUMzQyxXQUFLLFlBQVk7QUFFakIsV0FBSyxlQUFlLGdCQUFnQjtBQUdwQyxXQUFLLFdBQVcsQ0FBQyxTQUFTO0FBQ3RCLGlCQUFTLE1BQU0sTUFBTSxJQUFJO0FBRXpCLFlBQUksS0FBSyxpQkFBaUIsSUFBSTtBQUMxQixpQkFBTztBQUFBLFFBQ1g7QUFFQSxhQUFLLGdCQUFnQjtBQUNyQixlQUFPLEtBQUssaUJBQWlCO0FBQUEsTUFDakM7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQUVPLE1BQU0saUJBQWlCLENBQUM7QUFXeEIsV0FBUyxpQkFBaUIsV0FBVyxVQUFVLGNBQWM7QUFDaEUsbUJBQWUsYUFBYSxlQUFlLGNBQWMsQ0FBQztBQUMxRCxVQUFNLGVBQWUsSUFBSSxTQUFTLFdBQVcsVUFBVSxZQUFZO0FBQ25FLG1CQUFlLFdBQVcsS0FBSyxZQUFZO0FBQzNDLFdBQU8sTUFBTSxZQUFZLFlBQVk7QUFBQSxFQUN6QztBQVVPLFdBQVMsU0FBUyxXQUFXLFVBQVU7QUFDMUMsV0FBTyxpQkFBaUIsV0FBVyxVQUFVLEVBQUU7QUFBQSxFQUNuRDtBQVVPLFdBQVMsV0FBVyxXQUFXLFVBQVU7QUFDNUMsV0FBTyxpQkFBaUIsV0FBVyxVQUFVLENBQUM7QUFBQSxFQUNsRDtBQUVBLFdBQVMsZ0JBQWdCLFdBQVc7QUFHaEMsUUFBSSxZQUFZLFVBQVU7QUFHMUIsUUFBSSxlQUFlLFlBQVk7QUFHM0IsWUFBTSx1QkFBdUIsZUFBZSxXQUFXLE1BQU07QUFHN0QsZUFBUyxRQUFRLGVBQWUsV0FBVyxTQUFTLEdBQUcsU0FBUyxHQUFHLFNBQVMsR0FBRztBQUczRSxjQUFNLFdBQVcsZUFBZSxXQUFXO0FBRTNDLFlBQUksT0FBTyxVQUFVO0FBR3JCLGNBQU0sVUFBVSxTQUFTLFNBQVMsSUFBSTtBQUN0QyxZQUFJLFNBQVM7QUFFVCwrQkFBcUIsT0FBTyxPQUFPLENBQUM7QUFBQSxRQUN4QztBQUFBLE1BQ0o7QUFHQSxVQUFJLHFCQUFxQixXQUFXLEdBQUc7QUFDbkMsdUJBQWUsU0FBUztBQUFBLE1BQzVCLE9BQU87QUFDSCx1QkFBZSxhQUFhO0FBQUEsTUFDaEM7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQVNPLFdBQVMsYUFBYSxlQUFlO0FBRXhDLFFBQUk7QUFDSixRQUFJO0FBQ0EsZ0JBQVUsS0FBSyxNQUFNLGFBQWE7QUFBQSxJQUN0QyxTQUFTLEdBQVA7QUFDRSxZQUFNLFFBQVEsb0NBQW9DO0FBQ2xELFlBQU0sSUFBSSxNQUFNLEtBQUs7QUFBQSxJQUN6QjtBQUNBLG9CQUFnQixPQUFPO0FBQUEsRUFDM0I7QUFRTyxXQUFTLFdBQVcsV0FBVztBQUVsQyxVQUFNLFVBQVU7QUFBQSxNQUNaLE1BQU07QUFBQSxNQUNOLE1BQU0sQ0FBQyxFQUFFLE1BQU0sTUFBTSxTQUFTLEVBQUUsTUFBTSxDQUFDO0FBQUEsSUFDM0M7QUFHQSxvQkFBZ0IsT0FBTztBQUd2QixXQUFPLFlBQVksT0FBTyxLQUFLLFVBQVUsT0FBTyxDQUFDO0FBQUEsRUFDckQ7QUFFQSxXQUFTLGVBQWUsV0FBVztBQUUvQixXQUFPLGVBQWU7QUFHdEIsV0FBTyxZQUFZLE9BQU8sU0FBUztBQUFBLEVBQ3ZDO0FBU08sV0FBUyxVQUFVLGNBQWMsc0JBQXNCO0FBQzFELG1CQUFlLFNBQVM7QUFFeEIsUUFBSSxxQkFBcUIsU0FBUyxHQUFHO0FBQ2pDLDJCQUFxQixRQUFRLENBQUFBLGVBQWE7QUFDdEMsdUJBQWVBLFVBQVM7QUFBQSxNQUM1QixDQUFDO0FBQUEsSUFDTDtBQUFBLEVBQ0o7QUFpQkMsV0FBUyxZQUFZLFVBQVU7QUFDNUIsVUFBTSxZQUFZLFNBQVM7QUFFM0IsbUJBQWUsYUFBYSxlQUFlLFdBQVcsT0FBTyxPQUFLLE1BQU0sUUFBUTtBQUdoRixRQUFJLGVBQWUsV0FBVyxXQUFXLEdBQUc7QUFDeEMscUJBQWUsU0FBUztBQUFBLElBQzVCO0FBQUEsRUFDSjs7O0FDeE1PLE1BQU0sWUFBWSxDQUFDO0FBTzFCLFdBQVMsZUFBZTtBQUN2QixRQUFJLFFBQVEsSUFBSSxZQUFZLENBQUM7QUFDN0IsV0FBTyxPQUFPLE9BQU8sZ0JBQWdCLEtBQUssRUFBRTtBQUFBLEVBQzdDO0FBUUEsV0FBUyxjQUFjO0FBQ3RCLFdBQU8sS0FBSyxPQUFPLElBQUk7QUFBQSxFQUN4QjtBQUdBLE1BQUk7QUFDSixNQUFJLE9BQU8sUUFBUTtBQUNsQixpQkFBYTtBQUFBLEVBQ2QsT0FBTztBQUNOLGlCQUFhO0FBQUEsRUFDZDtBQWlCTyxXQUFTLEtBQUssTUFBTSxNQUFNLFNBQVM7QUFHekMsUUFBSSxXQUFXLE1BQU07QUFDcEIsZ0JBQVU7QUFBQSxJQUNYO0FBR0EsV0FBTyxJQUFJLFFBQVEsU0FBVSxTQUFTLFFBQVE7QUFHN0MsVUFBSTtBQUNKLFNBQUc7QUFDRixxQkFBYSxPQUFPLE1BQU0sV0FBVztBQUFBLE1BQ3RDLFNBQVMsVUFBVTtBQUVuQixVQUFJO0FBRUosVUFBSSxVQUFVLEdBQUc7QUFDaEIsd0JBQWdCLFdBQVcsV0FBWTtBQUN0QyxpQkFBTyxNQUFNLGFBQWEsT0FBTyw2QkFBNkIsVUFBVSxDQUFDO0FBQUEsUUFDMUUsR0FBRyxPQUFPO0FBQUEsTUFDWDtBQUdBLGdCQUFVLGNBQWM7QUFBQSxRQUN2QjtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDRDtBQUVBLFVBQUk7QUFDSCxjQUFNLFVBQVU7QUFBQSxVQUNmO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxRQUNEO0FBR1MsZUFBTyxZQUFZLE1BQU0sS0FBSyxVQUFVLE9BQU8sQ0FBQztBQUFBLE1BQ3BELFNBQVMsR0FBUDtBQUVFLGdCQUFRLE1BQU0sQ0FBQztBQUFBLE1BQ25CO0FBQUEsSUFDSixDQUFDO0FBQUEsRUFDTDtBQUVBLFNBQU8saUJBQWlCLENBQUMsSUFBSSxNQUFNLFlBQVk7QUFHM0MsUUFBSSxXQUFXLE1BQU07QUFDakIsZ0JBQVU7QUFBQSxJQUNkO0FBR0EsV0FBTyxJQUFJLFFBQVEsU0FBVSxTQUFTLFFBQVE7QUFHMUMsVUFBSTtBQUNKLFNBQUc7QUFDQyxxQkFBYSxLQUFLLE1BQU0sV0FBVztBQUFBLE1BQ3ZDLFNBQVMsVUFBVTtBQUVuQixVQUFJO0FBRUosVUFBSSxVQUFVLEdBQUc7QUFDYix3QkFBZ0IsV0FBVyxXQUFZO0FBQ25DLGlCQUFPLE1BQU0sb0JBQW9CLEtBQUssNkJBQTZCLFVBQVUsQ0FBQztBQUFBLFFBQ2xGLEdBQUcsT0FBTztBQUFBLE1BQ2Q7QUFHQSxnQkFBVSxjQUFjO0FBQUEsUUFDcEI7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLE1BQ0o7QUFFQSxVQUFJO0FBQ0EsY0FBTSxVQUFVO0FBQUEsVUFDeEI7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Q7QUFHUyxlQUFPLFlBQVksTUFBTSxLQUFLLFVBQVUsT0FBTyxDQUFDO0FBQUEsTUFDcEQsU0FBUyxHQUFQO0FBRUUsZ0JBQVEsTUFBTSxDQUFDO0FBQUEsTUFDbkI7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBVU8sV0FBUyxTQUFTLGlCQUFpQjtBQUV6QyxRQUFJO0FBQ0osUUFBSTtBQUNILGdCQUFVLEtBQUssTUFBTSxlQUFlO0FBQUEsSUFDckMsU0FBUyxHQUFQO0FBQ0QsWUFBTSxRQUFRLG9DQUFvQyxFQUFFLHFCQUFxQjtBQUN6RSxjQUFRLFNBQVMsS0FBSztBQUN0QixZQUFNLElBQUksTUFBTSxLQUFLO0FBQUEsSUFDdEI7QUFDQSxRQUFJLGFBQWEsUUFBUTtBQUN6QixRQUFJLGVBQWUsVUFBVTtBQUM3QixRQUFJLENBQUMsY0FBYztBQUNsQixZQUFNLFFBQVEsYUFBYTtBQUMzQixjQUFRLE1BQU0sS0FBSztBQUNuQixZQUFNLElBQUksTUFBTSxLQUFLO0FBQUEsSUFDdEI7QUFDQSxpQkFBYSxhQUFhLGFBQWE7QUFFdkMsV0FBTyxVQUFVO0FBRWpCLFFBQUksUUFBUSxPQUFPO0FBQ2xCLG1CQUFhLE9BQU8sUUFBUSxLQUFLO0FBQUEsSUFDbEMsT0FBTztBQUNOLG1CQUFhLFFBQVEsUUFBUSxNQUFNO0FBQUEsSUFDcEM7QUFBQSxFQUNEOzs7QUMxS0EsU0FBTyxLQUFLLENBQUM7QUFFTixXQUFTLFlBQVksYUFBYTtBQUN4QyxRQUFJO0FBQ0gsb0JBQWMsS0FBSyxNQUFNLFdBQVc7QUFBQSxJQUNyQyxTQUFTLEdBQVA7QUFDRCxjQUFRLE1BQU0sQ0FBQztBQUFBLElBQ2hCO0FBR0EsV0FBTyxLQUFLLE9BQU8sTUFBTSxDQUFDO0FBRzFCLFdBQU8sS0FBSyxXQUFXLEVBQUUsUUFBUSxDQUFDLGdCQUFnQjtBQUdqRCxhQUFPLEdBQUcsZUFBZSxPQUFPLEdBQUcsZ0JBQWdCLENBQUM7QUFHcEQsYUFBTyxLQUFLLFlBQVksWUFBWSxFQUFFLFFBQVEsQ0FBQyxlQUFlO0FBRzdELGVBQU8sR0FBRyxhQUFhLGNBQWMsT0FBTyxHQUFHLGFBQWEsZUFBZSxDQUFDO0FBRTVFLGVBQU8sS0FBSyxZQUFZLGFBQWEsV0FBVyxFQUFFLFFBQVEsQ0FBQyxlQUFlO0FBRXpFLGlCQUFPLEdBQUcsYUFBYSxZQUFZLGNBQWMsV0FBWTtBQUc1RCxnQkFBSSxVQUFVO0FBR2QscUJBQVMsVUFBVTtBQUNsQixvQkFBTSxPQUFPLENBQUMsRUFBRSxNQUFNLEtBQUssU0FBUztBQUNwQyxxQkFBTyxLQUFLLENBQUMsYUFBYSxZQUFZLFVBQVUsRUFBRSxLQUFLLEdBQUcsR0FBRyxNQUFNLE9BQU87QUFBQSxZQUMzRTtBQUdBLG9CQUFRLGFBQWEsU0FBVSxZQUFZO0FBQzFDLHdCQUFVO0FBQUEsWUFDWDtBQUdBLG9CQUFRLGFBQWEsV0FBWTtBQUNoQyxxQkFBTztBQUFBLFlBQ1I7QUFFQSxtQkFBTztBQUFBLFVBQ1IsRUFBRTtBQUFBLFFBQ0gsQ0FBQztBQUFBLE1BQ0YsQ0FBQztBQUFBLElBQ0YsQ0FBQztBQUFBLEVBQ0Y7OztBQ2xFQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWVPLFdBQVMsZUFBZTtBQUMzQixXQUFPLFNBQVMsT0FBTztBQUFBLEVBQzNCO0FBRU8sV0FBUyxrQkFBa0I7QUFDOUIsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQUVPLFdBQVMsOEJBQThCO0FBQzFDLFdBQU8sWUFBWSxPQUFPO0FBQUEsRUFDOUI7QUFFTyxXQUFTLHNCQUFzQjtBQUNsQyxXQUFPLFlBQVksTUFBTTtBQUFBLEVBQzdCO0FBRU8sV0FBUyxxQkFBcUI7QUFDakMsV0FBTyxZQUFZLE1BQU07QUFBQSxFQUM3QjtBQU9PLFdBQVMsZUFBZTtBQUMzQixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBUU8sV0FBUyxlQUFlLE9BQU87QUFDbEMsV0FBTyxZQUFZLE9BQU8sS0FBSztBQUFBLEVBQ25DO0FBT08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMscUJBQXFCO0FBQ2pDLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLHFCQUFxQjtBQUNqQyxXQUFPLEtBQUssMkJBQTJCO0FBQUEsRUFDM0M7QUFTTyxXQUFTLGNBQWMsT0FBTyxRQUFRO0FBQ3pDLFdBQU8sWUFBWSxRQUFRLFFBQVEsTUFBTSxNQUFNO0FBQUEsRUFDbkQ7QUFTTyxXQUFTLGdCQUFnQjtBQUM1QixXQUFPLEtBQUssc0JBQXNCO0FBQUEsRUFDdEM7QUFTTyxXQUFTLGlCQUFpQixPQUFPLFFBQVE7QUFDNUMsV0FBTyxZQUFZLFFBQVEsUUFBUSxNQUFNLE1BQU07QUFBQSxFQUNuRDtBQVNPLFdBQVMsaUJBQWlCLE9BQU8sUUFBUTtBQUM1QyxXQUFPLFlBQVksUUFBUSxRQUFRLE1BQU0sTUFBTTtBQUFBLEVBQ25EO0FBU08sV0FBUyxxQkFBcUIsR0FBRztBQUVwQyxXQUFPLFlBQVksV0FBVyxJQUFJLE1BQU0sSUFBSTtBQUFBLEVBQ2hEO0FBWU8sV0FBUyxrQkFBa0IsR0FBRyxHQUFHO0FBQ3BDLFdBQU8sWUFBWSxRQUFRLElBQUksTUFBTSxDQUFDO0FBQUEsRUFDMUM7QUFRTyxXQUFTLG9CQUFvQjtBQUNoQyxXQUFPLEtBQUsscUJBQXFCO0FBQUEsRUFDckM7QUFPTyxXQUFTLGFBQWE7QUFDekIsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMsYUFBYTtBQUN6QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxpQkFBaUI7QUFDN0IsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMsdUJBQXVCO0FBQ25DLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFPTyxXQUFTLG1CQUFtQjtBQUMvQixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBUU8sV0FBUyxvQkFBb0I7QUFDaEMsV0FBTyxLQUFLLDBCQUEwQjtBQUFBLEVBQzFDO0FBT08sV0FBUyxpQkFBaUI7QUFDN0IsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMsbUJBQW1CO0FBQy9CLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLG9CQUFvQjtBQUNoQyxXQUFPLEtBQUssMEJBQTBCO0FBQUEsRUFDMUM7QUFRTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLEtBQUssdUJBQXVCO0FBQUEsRUFDdkM7QUFXTyxXQUFTLDBCQUEwQixHQUFHLEdBQUcsR0FBRyxHQUFHO0FBQ2xELFFBQUksT0FBTyxLQUFLLFVBQVUsRUFBQyxHQUFHLEtBQUssR0FBRyxHQUFHLEtBQUssR0FBRyxHQUFHLEtBQUssR0FBRyxHQUFHLEtBQUssSUFBRyxDQUFDO0FBQ3hFLFdBQU8sWUFBWSxRQUFRLElBQUk7QUFBQSxFQUNuQzs7O0FDM1FBO0FBQUE7QUFBQTtBQUFBO0FBc0JPLFdBQVMsZUFBZTtBQUMzQixXQUFPLEtBQUsscUJBQXFCO0FBQUEsRUFDckM7OztBQ3hCQTtBQUFBO0FBQUE7QUFBQTtBQUtPLFdBQVMsZUFBZSxLQUFLO0FBQ2xDLFdBQU8sWUFBWSxRQUFRLEdBQUc7QUFBQSxFQUNoQzs7O0FDUEE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQW9CTyxXQUFTLGlCQUFpQixNQUFNO0FBQ25DLFdBQU8sS0FBSywyQkFBMkIsQ0FBQyxJQUFJLENBQUM7QUFBQSxFQUNqRDtBQVNPLFdBQVMsbUJBQW1CO0FBQy9CLFdBQU8sS0FBSyx5QkFBeUI7QUFBQSxFQUN6Qzs7O0FDMUJPLFdBQVMsMEJBQTBCLE9BQU87QUFFN0MsVUFBTSxVQUFVLE1BQU07QUFDdEIsVUFBTSxnQkFBZ0IsT0FBTyxpQkFBaUIsT0FBTztBQUNyRCxVQUFNLDJCQUEyQixjQUFjLGlCQUFpQix1QkFBdUIsRUFBRSxLQUFLO0FBQzlGLFlBQVEsMEJBQTBCO0FBQUEsTUFDOUIsS0FBSztBQUNEO0FBQUEsTUFDSixLQUFLO0FBQ0QsY0FBTSxlQUFlO0FBQ3JCO0FBQUEsTUFDSjtBQUVJLFlBQUksUUFBUSxtQkFBbUI7QUFDM0I7QUFBQSxRQUNKO0FBR0EsY0FBTSxZQUFZLE9BQU8sYUFBYTtBQUN0QyxjQUFNLGVBQWdCLFVBQVUsU0FBUyxFQUFFLFNBQVM7QUFDcEQsWUFBSSxjQUFjO0FBQ2QsbUJBQVMsSUFBSSxHQUFHLElBQUksVUFBVSxZQUFZLEtBQUs7QUFDM0Msa0JBQU0sUUFBUSxVQUFVLFdBQVcsQ0FBQztBQUNwQyxrQkFBTSxRQUFRLE1BQU0sZUFBZTtBQUNuQyxxQkFBUyxJQUFJLEdBQUcsSUFBSSxNQUFNLFFBQVEsS0FBSztBQUNuQyxvQkFBTSxPQUFPLE1BQU07QUFDbkIsa0JBQUksU0FBUyxpQkFBaUIsS0FBSyxNQUFNLEtBQUssR0FBRyxNQUFNLFNBQVM7QUFDNUQ7QUFBQSxjQUNKO0FBQUEsWUFDSjtBQUFBLFVBQ0o7QUFBQSxRQUNKO0FBRUEsWUFBSSxRQUFRLFlBQVksV0FBVyxRQUFRLFlBQVksWUFBWTtBQUMvRCxjQUFJLGdCQUFpQixDQUFDLFFBQVEsWUFBWSxDQUFDLFFBQVEsVUFBVztBQUMxRDtBQUFBLFVBQ0o7QUFBQSxRQUNKO0FBR0EsY0FBTSxlQUFlO0FBQUEsSUFDN0I7QUFBQSxFQUNKOzs7QUM1Qk8sV0FBUyxPQUFPO0FBQ25CLFdBQU8sWUFBWSxHQUFHO0FBQUEsRUFDMUI7QUFFTyxXQUFTLE9BQU87QUFDbkIsV0FBTyxZQUFZLEdBQUc7QUFBQSxFQUMxQjtBQUVPLFdBQVMsT0FBTztBQUNuQixXQUFPLFlBQVksR0FBRztBQUFBLEVBQzFCO0FBRU8sV0FBUyxjQUFjO0FBQzFCLFdBQU8sS0FBSyxvQkFBb0I7QUFBQSxFQUNwQztBQUdBLFNBQU8sVUFBVTtBQUFBLElBQ2IsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLEVBQ0o7QUFHQSxTQUFPLFFBQVE7QUFBQSxJQUNYO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0EsT0FBTztBQUFBLE1BQ0gsc0JBQXNCO0FBQUEsTUFDdEIsMkJBQTJCO0FBQUEsTUFDM0IsY0FBYztBQUFBLE1BQ2QsZUFBZTtBQUFBLE1BQ2YsaUJBQWlCO0FBQUEsTUFDakIsWUFBWTtBQUFBLE1BQ1osc0JBQXNCO0FBQUEsTUFDdEIsaUJBQWlCO0FBQUEsTUFDakIsY0FBYztBQUFBLElBQ2xCO0FBQUEsRUFDSjtBQUdBLE1BQUksT0FBTyxlQUFlO0FBQ3RCLFdBQU8sTUFBTSxZQUFZLE9BQU8sYUFBYTtBQUM3QyxXQUFPLE9BQU8sTUFBTTtBQUFBLEVBQ3hCO0FBR0EsTUFBSSxPQUFRO0FBQ1IsV0FBTyxPQUFPO0FBQUEsRUFDbEI7QUFFQSxNQUFJLFdBQVcsU0FBVSxHQUFHO0FBQ3hCLFFBQUksTUFBTSxPQUFPLGlCQUFpQixFQUFFLE1BQU0sRUFBRSxpQkFBaUIsT0FBTyxNQUFNLE1BQU0sZUFBZTtBQUMvRixRQUFJLEtBQUs7QUFDUCxZQUFNLElBQUksS0FBSztBQUFBLElBQ2pCO0FBRUEsUUFBSSxRQUFRLE9BQU8sTUFBTSxNQUFNLGNBQWM7QUFDekMsYUFBTztBQUFBLElBQ1g7QUFFQSxRQUFJLEVBQUUsWUFBWSxHQUFHO0FBRWpCLGFBQU87QUFBQSxJQUNYO0FBRUEsUUFBSSxFQUFFLFdBQVcsR0FBRztBQUVoQixhQUFPO0FBQUEsSUFDWDtBQUVBLFdBQU87QUFBQSxFQUNYO0FBRUEsU0FBTyxNQUFNLHVCQUF1QixTQUFVLFVBQVUsT0FBTztBQUMzRCxXQUFPLE1BQU0sTUFBTSxrQkFBa0I7QUFDckMsV0FBTyxNQUFNLE1BQU0sZUFBZTtBQUFBLEVBQ3RDO0FBRUEsU0FBTyxpQkFBaUIsYUFBYSxDQUFDLE1BQU07QUFHeEMsUUFBSSxPQUFPLE1BQU0sTUFBTSxZQUFZO0FBQy9CLGFBQU8sWUFBWSxZQUFZLE9BQU8sTUFBTSxNQUFNLFVBQVU7QUFDNUQsUUFBRSxlQUFlO0FBQ2pCO0FBQUEsSUFDSjtBQUVBLFFBQUksU0FBUyxDQUFDLEdBQUc7QUFDYixVQUFJLE9BQU8sTUFBTSxNQUFNLHNCQUFzQjtBQUV6QyxZQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sZUFBZSxFQUFFLFVBQVUsRUFBRSxPQUFPLGNBQWM7QUFDdkU7QUFBQSxRQUNKO0FBQUEsTUFDSjtBQUNBLFVBQUksT0FBTyxNQUFNLE1BQU0sc0JBQXNCO0FBQ3pDLGVBQU8sTUFBTSxNQUFNLGFBQWE7QUFBQSxNQUNwQyxPQUFPO0FBQ0gsVUFBRSxlQUFlO0FBQ2pCLGVBQU8sWUFBWSxNQUFNO0FBQUEsTUFDN0I7QUFDQTtBQUFBLElBQ0osT0FBTztBQUNILGFBQU8sTUFBTSxNQUFNLGFBQWE7QUFBQSxJQUNwQztBQUFBLEVBQ0osQ0FBQztBQUVELFNBQU8saUJBQWlCLFdBQVcsTUFBTTtBQUNyQyxXQUFPLE1BQU0sTUFBTSxhQUFhO0FBQUEsRUFDcEMsQ0FBQztBQUVELFdBQVMsVUFBVSxRQUFRO0FBQ3ZCLGFBQVMsZ0JBQWdCLE1BQU0sU0FBUyxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQ3JFLFdBQU8sTUFBTSxNQUFNLGFBQWE7QUFBQSxFQUNwQztBQUVBLFNBQU8saUJBQWlCLGFBQWEsU0FBVSxHQUFHO0FBQzlDLFFBQUksT0FBTyxNQUFNLE1BQU0sWUFBWTtBQUMvQixhQUFPLE1BQU0sTUFBTSxhQUFhO0FBQ2hDLFVBQUksZUFBZSxFQUFFLFlBQVksU0FBWSxFQUFFLFVBQVUsRUFBRTtBQUMzRCxVQUFJLGVBQWUsR0FBRztBQUNsQixlQUFPLFlBQVksTUFBTTtBQUN6QjtBQUFBLE1BQ0o7QUFBQSxJQUNKO0FBQ0EsUUFBSSxDQUFDLE9BQU8sTUFBTSxNQUFNLGNBQWM7QUFDbEM7QUFBQSxJQUNKO0FBQ0EsUUFBSSxPQUFPLE1BQU0sTUFBTSxpQkFBaUIsTUFBTTtBQUMxQyxhQUFPLE1BQU0sTUFBTSxnQkFBZ0IsU0FBUyxnQkFBZ0IsTUFBTTtBQUFBLElBQ3RFO0FBQ0EsUUFBSSxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLG1CQUFtQixPQUFPLGNBQWMsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLGlCQUFpQjtBQUMzSSxlQUFTLGdCQUFnQixNQUFNLFNBQVM7QUFBQSxJQUM1QztBQUNBLFFBQUksY0FBYyxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQ3JFLFFBQUksYUFBYSxFQUFFLFVBQVUsT0FBTyxNQUFNLE1BQU07QUFDaEQsUUFBSSxZQUFZLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUMvQyxRQUFJLGVBQWUsT0FBTyxjQUFjLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUd2RSxRQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLE9BQU8sTUFBTSxNQUFNLGVBQWUsUUFBVztBQUMzRyxnQkFBVTtBQUFBLElBQ2QsV0FBVyxlQUFlO0FBQWMsZ0JBQVUsV0FBVztBQUFBLGFBQ3BELGNBQWM7QUFBYyxnQkFBVSxXQUFXO0FBQUEsYUFDakQsY0FBYztBQUFXLGdCQUFVLFdBQVc7QUFBQSxhQUM5QyxhQUFhO0FBQWEsZ0JBQVUsV0FBVztBQUFBLGFBQy9DO0FBQVksZ0JBQVUsVUFBVTtBQUFBLGFBQ2hDO0FBQVcsZ0JBQVUsVUFBVTtBQUFBLGFBQy9CO0FBQWMsZ0JBQVUsVUFBVTtBQUFBLGFBQ2xDO0FBQWEsZ0JBQVUsVUFBVTtBQUFBLEVBRTlDLENBQUM7QUFHRCxTQUFPLGlCQUFpQixlQUFlLFNBQVUsR0FBRztBQUVoRCxRQUFJO0FBQU87QUFFWCxRQUFJLE9BQU8sTUFBTSxNQUFNLDJCQUEyQjtBQUM5QyxRQUFFLGVBQWU7QUFBQSxJQUNyQixPQUFPO0FBQ0gsTUFBWSwwQkFBMEIsQ0FBQztBQUFBLElBQzNDO0FBQUEsRUFDSixDQUFDO0FBRUQsU0FBTyxZQUFZLGVBQWU7IiwKICAibmFtZXMiOiBbImV2ZW50TmFtZSJdCn0K
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.go b/v2/internal/frontend/runtime/runtime_dev_desktop.go
deleted file mode 100644
index c0dcb1fc5..000000000
--- a/v2/internal/frontend/runtime/runtime_dev_desktop.go
+++ /dev/null
@@ -1,8 +0,0 @@
-//go:build dev || bindings || (!dev && !production && !bindings)
-
-package runtime
-
-import _ "embed"
-
-//go:embed runtime_dev_desktop.js
-var RuntimeDesktopJS []byte
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.js b/v2/internal/frontend/runtime/runtime_dev_desktop.js
deleted file mode 100644
index 6bfce9f5b..000000000
--- a/v2/internal/frontend/runtime/runtime_dev_desktop.js
+++ /dev/null
@@ -1,586 +0,0 @@
-(() => {
- var __defProp = Object.defineProperty;
- var __export = (target, all) => {
- for (var name in all)
- __defProp(target, name, { get: all[name], enumerable: true });
- };
-
- // desktop/log.js
- var log_exports = {};
- __export(log_exports, {
- LogDebug: () => LogDebug,
- LogError: () => LogError,
- LogFatal: () => LogFatal,
- LogInfo: () => LogInfo,
- LogLevel: () => LogLevel,
- LogPrint: () => LogPrint,
- LogTrace: () => LogTrace,
- LogWarning: () => LogWarning,
- SetLogLevel: () => SetLogLevel
- });
- function sendLogMessage(level, message) {
- window.WailsInvoke("L" + level + message);
- }
- function LogTrace(message) {
- sendLogMessage("T", message);
- }
- function LogPrint(message) {
- sendLogMessage("P", message);
- }
- function LogDebug(message) {
- sendLogMessage("D", message);
- }
- function LogInfo(message) {
- sendLogMessage("I", message);
- }
- function LogWarning(message) {
- sendLogMessage("W", message);
- }
- function LogError(message) {
- sendLogMessage("E", message);
- }
- function LogFatal(message) {
- sendLogMessage("F", message);
- }
- function SetLogLevel(loglevel) {
- sendLogMessage("S", loglevel);
- }
- var LogLevel = {
- TRACE: 1,
- DEBUG: 2,
- INFO: 3,
- WARNING: 4,
- ERROR: 5
- };
-
- // desktop/events.js
- var Listener = class {
- /**
- * Creates an instance of Listener.
- * @param {string} eventName
- * @param {function} callback
- * @param {number} maxCallbacks
- * @memberof Listener
- */
- constructor(eventName, callback, maxCallbacks) {
- this.eventName = eventName;
- this.maxCallbacks = maxCallbacks || -1;
- this.Callback = (data) => {
- callback.apply(null, data);
- if (this.maxCallbacks === -1) {
- return false;
- }
- this.maxCallbacks -= 1;
- return this.maxCallbacks === 0;
- };
- }
- };
- var eventListeners = {};
- function EventsOnMultiple(eventName, callback, maxCallbacks) {
- eventListeners[eventName] = eventListeners[eventName] || [];
- const thisListener = new Listener(eventName, callback, maxCallbacks);
- eventListeners[eventName].push(thisListener);
- return () => listenerOff(thisListener);
- }
- function EventsOn(eventName, callback) {
- return EventsOnMultiple(eventName, callback, -1);
- }
- function EventsOnce(eventName, callback) {
- return EventsOnMultiple(eventName, callback, 1);
- }
- function notifyListeners(eventData) {
- let eventName = eventData.name;
- if (eventListeners[eventName]) {
- const newEventListenerList = eventListeners[eventName].slice();
- for (let count = eventListeners[eventName].length - 1; count >= 0; count -= 1) {
- const listener = eventListeners[eventName][count];
- let data = eventData.data;
- const destroy = listener.Callback(data);
- if (destroy) {
- newEventListenerList.splice(count, 1);
- }
- }
- if (newEventListenerList.length === 0) {
- removeListener(eventName);
- } else {
- eventListeners[eventName] = newEventListenerList;
- }
- }
- }
- function EventsNotify(notifyMessage) {
- let message;
- try {
- message = JSON.parse(notifyMessage);
- } catch (e) {
- const error = "Invalid JSON passed to Notify: " + notifyMessage;
- throw new Error(error);
- }
- notifyListeners(message);
- }
- function EventsEmit(eventName) {
- const payload = {
- name: eventName,
- data: [].slice.apply(arguments).slice(1)
- };
- notifyListeners(payload);
- window.WailsInvoke("EE" + JSON.stringify(payload));
- }
- function removeListener(eventName) {
- delete eventListeners[eventName];
- window.WailsInvoke("EX" + eventName);
- }
- function EventsOff(eventName, ...additionalEventNames) {
- removeListener(eventName);
- if (additionalEventNames.length > 0) {
- additionalEventNames.forEach((eventName2) => {
- removeListener(eventName2);
- });
- }
- }
- function listenerOff(listener) {
- const eventName = listener.eventName;
- eventListeners[eventName] = eventListeners[eventName].filter((l) => l !== listener);
- if (eventListeners[eventName].length === 0) {
- removeListener(eventName);
- }
- }
-
- // desktop/calls.js
- var callbacks = {};
- function cryptoRandom() {
- var array = new Uint32Array(1);
- return window.crypto.getRandomValues(array)[0];
- }
- function basicRandom() {
- return Math.random() * 9007199254740991;
- }
- var randomFunc;
- if (window.crypto) {
- randomFunc = cryptoRandom;
- } else {
- randomFunc = basicRandom;
- }
- function Call(name, args, timeout) {
- if (timeout == null) {
- timeout = 0;
- }
- return new Promise(function(resolve, reject) {
- var callbackID;
- do {
- callbackID = name + "-" + randomFunc();
- } while (callbacks[callbackID]);
- var timeoutHandle;
- if (timeout > 0) {
- timeoutHandle = setTimeout(function() {
- reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
- }, timeout);
- }
- callbacks[callbackID] = {
- timeoutHandle,
- reject,
- resolve
- };
- try {
- const payload = {
- name,
- args,
- callbackID
- };
- window.WailsInvoke("C" + JSON.stringify(payload));
- } catch (e) {
- console.error(e);
- }
- });
- }
- window.ObfuscatedCall = (id, args, timeout) => {
- if (timeout == null) {
- timeout = 0;
- }
- return new Promise(function(resolve, reject) {
- var callbackID;
- do {
- callbackID = id + "-" + randomFunc();
- } while (callbacks[callbackID]);
- var timeoutHandle;
- if (timeout > 0) {
- timeoutHandle = setTimeout(function() {
- reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID));
- }, timeout);
- }
- callbacks[callbackID] = {
- timeoutHandle,
- reject,
- resolve
- };
- try {
- const payload = {
- id,
- args,
- callbackID
- };
- window.WailsInvoke("c" + JSON.stringify(payload));
- } catch (e) {
- console.error(e);
- }
- });
- };
- function Callback(incomingMessage) {
- let message;
- try {
- message = JSON.parse(incomingMessage);
- } catch (e) {
- const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
- runtime.LogDebug(error);
- throw new Error(error);
- }
- let callbackID = message.callbackid;
- let callbackData = callbacks[callbackID];
- if (!callbackData) {
- const error = `Callback '${callbackID}' not registered!!!`;
- console.error(error);
- throw new Error(error);
- }
- clearTimeout(callbackData.timeoutHandle);
- delete callbacks[callbackID];
- if (message.error) {
- callbackData.reject(message.error);
- } else {
- callbackData.resolve(message.result);
- }
- }
-
- // desktop/bindings.js
- window.go = {};
- function SetBindings(bindingsMap) {
- try {
- bindingsMap = JSON.parse(bindingsMap);
- } catch (e) {
- console.error(e);
- }
- window.go = window.go || {};
- Object.keys(bindingsMap).forEach((packageName) => {
- window.go[packageName] = window.go[packageName] || {};
- Object.keys(bindingsMap[packageName]).forEach((structName) => {
- window.go[packageName][structName] = window.go[packageName][structName] || {};
- Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
- window.go[packageName][structName][methodName] = function() {
- let timeout = 0;
- function dynamic() {
- const args = [].slice.call(arguments);
- return Call([packageName, structName, methodName].join("."), args, timeout);
- }
- dynamic.setTimeout = function(newTimeout) {
- timeout = newTimeout;
- };
- dynamic.getTimeout = function() {
- return timeout;
- };
- return dynamic;
- }();
- });
- });
- });
- }
-
- // desktop/window.js
- var window_exports = {};
- __export(window_exports, {
- WindowCenter: () => WindowCenter,
- WindowFullscreen: () => WindowFullscreen,
- WindowGetPosition: () => WindowGetPosition,
- WindowGetSize: () => WindowGetSize,
- WindowHide: () => WindowHide,
- WindowIsFullscreen: () => WindowIsFullscreen,
- WindowIsMaximised: () => WindowIsMaximised,
- WindowIsMinimised: () => WindowIsMinimised,
- WindowIsNormal: () => WindowIsNormal,
- WindowMaximise: () => WindowMaximise,
- WindowMinimise: () => WindowMinimise,
- WindowReload: () => WindowReload,
- WindowReloadApp: () => WindowReloadApp,
- WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop,
- WindowSetBackgroundColour: () => WindowSetBackgroundColour,
- WindowSetDarkTheme: () => WindowSetDarkTheme,
- WindowSetLightTheme: () => WindowSetLightTheme,
- WindowSetMaxSize: () => WindowSetMaxSize,
- WindowSetMinSize: () => WindowSetMinSize,
- WindowSetPosition: () => WindowSetPosition,
- WindowSetSize: () => WindowSetSize,
- WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme,
- WindowSetTitle: () => WindowSetTitle,
- WindowShow: () => WindowShow,
- WindowToggleMaximise: () => WindowToggleMaximise,
- WindowUnfullscreen: () => WindowUnfullscreen,
- WindowUnmaximise: () => WindowUnmaximise,
- WindowUnminimise: () => WindowUnminimise
- });
- function WindowReload() {
- window.location.reload();
- }
- function WindowReloadApp() {
- window.WailsInvoke("WR");
- }
- function WindowSetSystemDefaultTheme() {
- window.WailsInvoke("WASDT");
- }
- function WindowSetLightTheme() {
- window.WailsInvoke("WALT");
- }
- function WindowSetDarkTheme() {
- window.WailsInvoke("WADT");
- }
- function WindowCenter() {
- window.WailsInvoke("Wc");
- }
- function WindowSetTitle(title) {
- window.WailsInvoke("WT" + title);
- }
- function WindowFullscreen() {
- window.WailsInvoke("WF");
- }
- function WindowUnfullscreen() {
- window.WailsInvoke("Wf");
- }
- function WindowIsFullscreen() {
- return Call(":wails:WindowIsFullscreen");
- }
- function WindowSetSize(width, height) {
- window.WailsInvoke("Ws:" + width + ":" + height);
- }
- function WindowGetSize() {
- return Call(":wails:WindowGetSize");
- }
- function WindowSetMaxSize(width, height) {
- window.WailsInvoke("WZ:" + width + ":" + height);
- }
- function WindowSetMinSize(width, height) {
- window.WailsInvoke("Wz:" + width + ":" + height);
- }
- function WindowSetAlwaysOnTop(b) {
- window.WailsInvoke("WATP:" + (b ? "1" : "0"));
- }
- function WindowSetPosition(x, y) {
- window.WailsInvoke("Wp:" + x + ":" + y);
- }
- function WindowGetPosition() {
- return Call(":wails:WindowGetPos");
- }
- function WindowHide() {
- window.WailsInvoke("WH");
- }
- function WindowShow() {
- window.WailsInvoke("WS");
- }
- function WindowMaximise() {
- window.WailsInvoke("WM");
- }
- function WindowToggleMaximise() {
- window.WailsInvoke("Wt");
- }
- function WindowUnmaximise() {
- window.WailsInvoke("WU");
- }
- function WindowIsMaximised() {
- return Call(":wails:WindowIsMaximised");
- }
- function WindowMinimise() {
- window.WailsInvoke("Wm");
- }
- function WindowUnminimise() {
- window.WailsInvoke("Wu");
- }
- function WindowIsMinimised() {
- return Call(":wails:WindowIsMinimised");
- }
- function WindowIsNormal() {
- return Call(":wails:WindowIsNormal");
- }
- function WindowSetBackgroundColour(R, G, B, A) {
- let rgba = JSON.stringify({ r: R || 0, g: G || 0, b: B || 0, a: A || 255 });
- window.WailsInvoke("Wr:" + rgba);
- }
-
- // desktop/screen.js
- var screen_exports = {};
- __export(screen_exports, {
- ScreenGetAll: () => ScreenGetAll
- });
- function ScreenGetAll() {
- return Call(":wails:ScreenGetAll");
- }
-
- // desktop/browser.js
- var browser_exports = {};
- __export(browser_exports, {
- BrowserOpenURL: () => BrowserOpenURL
- });
- function BrowserOpenURL(url) {
- window.WailsInvoke("BO:" + url);
- }
-
- // desktop/clipboard.js
- var clipboard_exports = {};
- __export(clipboard_exports, {
- ClipboardGetText: () => ClipboardGetText,
- ClipboardSetText: () => ClipboardSetText
- });
- function ClipboardSetText(text) {
- return Call(":wails:ClipboardSetText", [text]);
- }
- function ClipboardGetText() {
- return Call(":wails:ClipboardGetText");
- }
-
- // desktop/main.js
- function Quit() {
- window.WailsInvoke("Q");
- }
- function Show() {
- window.WailsInvoke("S");
- }
- function Hide() {
- window.WailsInvoke("H");
- }
- function Environment() {
- return Call(":wails:Environment");
- }
- window.runtime = {
- ...log_exports,
- ...window_exports,
- ...browser_exports,
- ...screen_exports,
- ...clipboard_exports,
- EventsOn,
- EventsOnce,
- EventsOnMultiple,
- EventsEmit,
- EventsOff,
- Environment,
- Show,
- Hide,
- Quit
- };
- window.wails = {
- Callback,
- EventsNotify,
- SetBindings,
- eventListeners,
- callbacks,
- flags: {
- disableScrollbarDrag: false,
- disableWailsDefaultContextMenu: false,
- enableResize: false,
- defaultCursor: null,
- borderThickness: 6,
- shouldDrag: false,
- deferDragToMouseMove: true,
- cssDragProperty: "--wails-draggable",
- cssDragValue: "drag"
- }
- };
- if (window.wailsbindings) {
- window.wails.SetBindings(window.wailsbindings);
- delete window.wails.SetBindings;
- }
- if (false) {
- delete window.wailsbindings;
- }
- var dragTest = function(e) {
- var val = window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);
- if (val) {
- val = val.trim();
- }
- if (val !== window.wails.flags.cssDragValue) {
- return false;
- }
- if (e.buttons !== 1) {
- return false;
- }
- if (e.detail !== 1) {
- return false;
- }
- return true;
- };
- window.wails.setCSSDragProperties = function(property, value) {
- window.wails.flags.cssDragProperty = property;
- window.wails.flags.cssDragValue = value;
- };
- window.addEventListener("mousedown", (e) => {
- if (window.wails.flags.resizeEdge) {
- window.WailsInvoke("resize:" + window.wails.flags.resizeEdge);
- e.preventDefault();
- return;
- }
- if (dragTest(e)) {
- if (window.wails.flags.disableScrollbarDrag) {
- if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
- return;
- }
- }
- if (window.wails.flags.deferDragToMouseMove) {
- window.wails.flags.shouldDrag = true;
- } else {
- e.preventDefault();
- window.WailsInvoke("drag");
- }
- return;
- } else {
- window.wails.flags.shouldDrag = false;
- }
- });
- window.addEventListener("mouseup", () => {
- window.wails.flags.shouldDrag = false;
- });
- function setResize(cursor) {
- document.documentElement.style.cursor = cursor || window.wails.flags.defaultCursor;
- window.wails.flags.resizeEdge = cursor;
- }
- window.addEventListener("mousemove", function(e) {
- if (window.wails.flags.shouldDrag) {
- window.wails.flags.shouldDrag = false;
- let mousePressed = e.buttons !== void 0 ? e.buttons : e.which;
- if (mousePressed > 0) {
- window.WailsInvoke("drag");
- return;
- }
- }
- if (!window.wails.flags.enableResize) {
- return;
- }
- if (window.wails.flags.defaultCursor == null) {
- window.wails.flags.defaultCursor = document.documentElement.style.cursor;
- }
- if (window.outerWidth - e.clientX < window.wails.flags.borderThickness && window.outerHeight - e.clientY < window.wails.flags.borderThickness) {
- document.documentElement.style.cursor = "se-resize";
- }
- let rightBorder = window.outerWidth - e.clientX < window.wails.flags.borderThickness;
- let leftBorder = e.clientX < window.wails.flags.borderThickness;
- let topBorder = e.clientY < window.wails.flags.borderThickness;
- let bottomBorder = window.outerHeight - e.clientY < window.wails.flags.borderThickness;
- if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && window.wails.flags.resizeEdge !== void 0) {
- setResize();
- } else if (rightBorder && bottomBorder)
- setResize("se-resize");
- else if (leftBorder && bottomBorder)
- setResize("sw-resize");
- else if (leftBorder && topBorder)
- setResize("nw-resize");
- else if (topBorder && rightBorder)
- setResize("ne-resize");
- else if (leftBorder)
- setResize("w-resize");
- else if (topBorder)
- setResize("n-resize");
- else if (bottomBorder)
- setResize("s-resize");
- else if (rightBorder)
- setResize("e-resize");
- });
- window.addEventListener("contextmenu", function(e) {
- if (window.wails.flags.disableWailsDefaultContextMenu) {
- e.preventDefault();
- }
- });
- window.WailsInvoke("runtime:ready");
-})();
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2NsaXBib2FyZC5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxuICAgICAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgLT0gMTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmNlIHRoZW4gZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAxKTtcbn1cblxuZnVuY3Rpb24gbm90aWZ5TGlzdGVuZXJzKGV2ZW50RGF0YSkge1xuXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXG4gICAgbGV0IGV2ZW50TmFtZSA9IGV2ZW50RGF0YS5uYW1lO1xuXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcblxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcbiAgICAgICAgY29uc3QgbmV3RXZlbnRMaXN0ZW5lckxpc3QgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnNsaWNlKCk7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmxlbmd0aCAtIDE7IGNvdW50ID49IDA7IGNvdW50IC09IDEpIHtcblxuICAgICAgICAgICAgLy8gR2V0IG5leHQgbGlzdGVuZXJcbiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXVtjb3VudF07XG5cbiAgICAgICAgICAgIGxldCBkYXRhID0gZXZlbnREYXRhLmRhdGE7XG5cbiAgICAgICAgICAgIC8vIERvIHRoZSBjYWxsYmFja1xuICAgICAgICAgICAgY29uc3QgZGVzdHJveSA9IGxpc3RlbmVyLkNhbGxiYWNrKGRhdGEpO1xuICAgICAgICAgICAgaWYgKGRlc3Ryb3kpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgbGlzdGVuZXIgaW5kaWNhdGVkIHRvIGRlc3Ryb3kgaXRzZWxmLCBhZGQgaXQgdG8gdGhlIGRlc3Ryb3kgbGlzdFxuICAgICAgICAgICAgICAgIG5ld0V2ZW50TGlzdGVuZXJMaXN0LnNwbGljZShjb3VudCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgY2FsbGJhY2tzIHdpdGggbmV3IGxpc3Qgb2YgbGlzdGVuZXJzXG4gICAgICAgIGlmIChuZXdFdmVudExpc3RlbmVyTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmVudExpc3RlbmVyc1tldmVudE5hbWVdID0gbmV3RXZlbnRMaXN0ZW5lckxpc3Q7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogTm90aWZ5IGluZm9ybXMgZnJvbnRlbmQgbGlzdGVuZXJzIHRoYXQgYW4gZXZlbnQgd2FzIGVtaXR0ZWQgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBub3RpZnlNZXNzYWdlIC0gZW5jb2RlZCBub3RpZmljYXRpb24gbWVzc2FnZVxuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNOb3RpZnkobm90aWZ5TWVzc2FnZSkge1xuICAgIC8vIFBhcnNlIHRoZSBtZXNzYWdlXG4gICAgbGV0IG1lc3NhZ2U7XG4gICAgdHJ5IHtcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2Uobm90aWZ5TWVzc2FnZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zdCBlcnJvciA9ICdJbnZhbGlkIEpTT04gcGFzc2VkIHRvIE5vdGlmeTogJyArIG5vdGlmeU1lc3NhZ2U7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG4gICAgfVxuICAgIG5vdGlmeUxpc3RlbmVycyhtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBFbWl0IGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNFbWl0KGV2ZW50TmFtZSkge1xuXG4gICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgbmFtZTogZXZlbnROYW1lLFxuICAgICAgICBkYXRhOiBbXS5zbGljZS5hcHBseShhcmd1bWVudHMpLnNsaWNlKDEpLFxuICAgIH07XG5cbiAgICAvLyBOb3RpZnkgSlMgbGlzdGVuZXJzXG4gICAgbm90aWZ5TGlzdGVuZXJzKHBheWxvYWQpO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRUUnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xufVxuXG5mdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpIHtcbiAgICAvLyBSZW1vdmUgbG9jYWwgbGlzdGVuZXJzXG4gICAgZGVsZXRlIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV07XG5cbiAgICAvLyBOb3RpZnkgR28gbGlzdGVuZXJzXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFWCcgKyBldmVudE5hbWUpO1xufVxuXG4vKipcbiAqIE9mZiB1bnJlZ2lzdGVycyBhIGxpc3RlbmVyIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE9uLFxuICogb3B0aW9uYWxseSBtdWx0aXBsZSBsaXN0ZW5lcmVzIGNhbiBiZSB1bnJlZ2lzdGVyZWQgdmlhIGBhZGRpdGlvbmFsRXZlbnROYW1lc2BcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKiBAcGFyYW0gIHsuLi5zdHJpbmd9IGFkZGl0aW9uYWxFdmVudE5hbWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPZmYoZXZlbnROYW1lLCAuLi5hZGRpdGlvbmFsRXZlbnROYW1lcykge1xuICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSlcblxuICAgIGlmIChhZGRpdGlvbmFsRXZlbnROYW1lcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGFkZGl0aW9uYWxFdmVudE5hbWVzLmZvckVhY2goZXZlbnROYW1lID0+IHtcbiAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSlcbiAgICAgICAgfSlcbiAgICB9XG59XG5cbi8qKlxuICogT2ZmIHVucmVnaXN0ZXJzIGFsbCBldmVudCBsaXN0ZW5lcnMgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggT25cbiAqL1xuIGV4cG9ydCBmdW5jdGlvbiBFdmVudHNPZmZBbGwoKSB7XG4gICAgY29uc3QgZXZlbnROYW1lcyA9IE9iamVjdC5rZXlzKGV2ZW50TGlzdGVuZXJzKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSAhPT0gZXZlbnROYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWVzW2ldKTtcbiAgICB9XG59XG5cbi8qKlxuICogbGlzdGVuZXJPZmYgdW5yZWdpc3RlcnMgYSBsaXN0ZW5lciBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBFdmVudHNPblxuICpcbiAqIEBwYXJhbSB7TGlzdGVuZXJ9IGxpc3RlbmVyXG4gKi9cbiBmdW5jdGlvbiBsaXN0ZW5lck9mZihsaXN0ZW5lcikge1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcbiAgICAvLyBSZW1vdmUgbG9jYWwgbGlzdGVuZXJcbiAgICBldmVudExpc3RlbmVyc1tldmVudE5hbWVdID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5maWx0ZXIobCA9PiBsICE9PSBsaXN0ZW5lcik7XG5cbiAgICAvLyBDbGVhbiB1cCBpZiB0aGVyZSBhcmUgbm8gZXZlbnQgbGlzdGVuZXJzIGxlZnRcbiAgICBpZiAoZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKTtcbiAgICB9XG59XG4iLCAiLypcbiBfICAgICAgIF9fICAgICAgXyBfX1xufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbmV4cG9ydCBjb25zdCBjYWxsYmFja3MgPSB7fTtcblxuLyoqXG4gKiBSZXR1cm5zIGEgbnVtYmVyIGZyb20gdGhlIG5hdGl2ZSBicm93c2VyIHJhbmRvbSBmdW5jdGlvblxuICpcbiAqIEByZXR1cm5zIG51bWJlclxuICovXG5mdW5jdGlvbiBjcnlwdG9SYW5kb20oKSB7XG5cdHZhciBhcnJheSA9IG5ldyBVaW50MzJBcnJheSgxKTtcblx0cmV0dXJuIHdpbmRvdy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KVswXTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgbnVtYmVyIHVzaW5nIGRhIG9sZC1za29vbCBNYXRoLlJhbmRvbVxuICogSSBsaWtlcyB0byBjYWxsIGl0IExPTFJhbmRvbVxuICpcbiAqIEByZXR1cm5zIG51bWJlclxuICovXG5mdW5jdGlvbiBiYXNpY1JhbmRvbSgpIHtcblx0cmV0dXJuIE1hdGgucmFuZG9tKCkgKiA5MDA3MTk5MjU0NzQwOTkxO1xufVxuXG4vLyBQaWNrIGEgcmFuZG9tIG51bWJlciBmdW5jdGlvbiBiYXNlZCBvbiBicm93c2VyIGNhcGFiaWxpdHlcbnZhciByYW5kb21GdW5jO1xuaWYgKHdpbmRvdy5jcnlwdG8pIHtcblx0cmFuZG9tRnVuYyA9IGNyeXB0b1JhbmRvbTtcbn0gZWxzZSB7XG5cdHJhbmRvbUZ1bmMgPSBiYXNpY1JhbmRvbTtcbn1cblxuXG4vKipcbiAqIENhbGwgc2VuZHMgYSBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kIHRvIGNhbGwgdGhlIGJpbmRpbmcgd2l0aCB0aGVcbiAqIGdpdmVuIGRhdGEuIEEgcHJvbWlzZSBpcyByZXR1cm5lZCBhbmQgd2lsbCBiZSBjb21wbGV0ZWQgd2hlbiB0aGVcbiAqIGJhY2tlbmQgcmVzcG9uZHMuIFRoaXMgd2lsbCBiZSByZXNvbHZlZCB3aGVuIHRoZSBjYWxsIHdhcyBzdWNjZXNzZnVsXG4gKiBvciByZWplY3RlZCBpZiBhbiBlcnJvciBpcyBwYXNzZWQgYmFjay5cbiAqIFRoZXJlIGlzIGEgdGltZW91dCBtZWNoYW5pc20uIElmIHRoZSBjYWxsIGRvZXNuJ3QgcmVzcG9uZCBpbiB0aGUgZ2l2ZW5cbiAqIHRpbWUgKGluIG1pbGxpc2Vjb25kcykgdGhlbiB0aGUgcHJvbWlzZSBpcyByZWplY3RlZC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHthbnk9fSBhcmdzXG4gKiBAcGFyYW0ge251bWJlcj19IHRpbWVvdXRcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG5hbWUsIGFyZ3MsIHRpbWVvdXQpIHtcblxuXHQvLyBUaW1lb3V0IGluZmluaXRlIGJ5IGRlZmF1bHRcblx0aWYgKHRpbWVvdXQgPT0gbnVsbCkge1xuXHRcdHRpbWVvdXQgPSAwO1xuXHR9XG5cblx0Ly8gQ3JlYXRlIGEgcHJvbWlzZVxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG5cdFx0Ly8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcblx0XHR2YXIgY2FsbGJhY2tJRDtcblx0XHRkbyB7XG5cdFx0XHRjYWxsYmFja0lEID0gbmFtZSArICctJyArIHJhbmRvbUZ1bmMoKTtcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG5cdFx0dmFyIHRpbWVvdXRIYW5kbGU7XG5cdFx0Ly8gU2V0IHRpbWVvdXRcblx0XHRpZiAodGltZW91dCA+IDApIHtcblx0XHRcdHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XG5cdFx0XHR9LCB0aW1lb3V0KTtcblx0XHR9XG5cblx0XHQvLyBTdG9yZSBjYWxsYmFja1xuXHRcdGNhbGxiYWNrc1tjYWxsYmFja0lEXSA9IHtcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXG5cdFx0XHRyZWplY3Q6IHJlamVjdCxcblx0XHRcdHJlc29sdmU6IHJlc29sdmVcblx0XHR9O1xuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGFyZ3MsXG5cdFx0XHRcdGNhbGxiYWNrSUQsXG5cdFx0XHR9O1xuXG4gICAgICAgICAgICAvLyBNYWtlIHRoZSBjYWxsXG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0MnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxud2luZG93Lk9iZnVzY2F0ZWRDYWxsID0gKGlkLCBhcmdzLCB0aW1lb3V0KSA9PiB7XG5cbiAgICAvLyBUaW1lb3V0IGluZmluaXRlIGJ5IGRlZmF1bHRcbiAgICBpZiAodGltZW91dCA9PSBudWxsKSB7XG4gICAgICAgIHRpbWVvdXQgPSAwO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhIHByb21pc2VcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG4gICAgICAgIC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXG4gICAgICAgIHZhciBjYWxsYmFja0lEO1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICBjYWxsYmFja0lEID0gaWQgKyAnLScgKyByYW5kb21GdW5jKCk7XG4gICAgICAgIH0gd2hpbGUgKGNhbGxiYWNrc1tjYWxsYmFja0lEXSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXRIYW5kbGU7XG4gICAgICAgIC8vIFNldCB0aW1lb3V0XG4gICAgICAgIGlmICh0aW1lb3V0ID4gMCkge1xuICAgICAgICAgICAgdGltZW91dEhhbmRsZSA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignQ2FsbCB0byBtZXRob2QgJyArIGlkICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XG4gICAgICAgICAgICB9LCB0aW1lb3V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0b3JlIGNhbGxiYWNrXG4gICAgICAgIGNhbGxiYWNrc1tjYWxsYmFja0lEXSA9IHtcbiAgICAgICAgICAgIHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXG4gICAgICAgICAgICByZWplY3Q6IHJlamVjdCxcbiAgICAgICAgICAgIHJlc29sdmU6IHJlc29sdmVcbiAgICAgICAgfTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHtcblx0XHRcdFx0aWQsXG5cdFx0XHRcdGFyZ3MsXG5cdFx0XHRcdGNhbGxiYWNrSUQsXG5cdFx0XHR9O1xuXG4gICAgICAgICAgICAvLyBNYWtlIHRoZSBjYWxsXG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ2MnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cblxuLyoqXG4gKiBDYWxsZWQgYnkgdGhlIGJhY2tlbmQgdG8gcmV0dXJuIGRhdGEgdG8gYSBwcmV2aW91c2x5IGNhbGxlZFxuICogYmluZGluZyBpbnZvY2F0aW9uXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGluY29taW5nTWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbGJhY2soaW5jb21pbmdNZXNzYWdlKSB7XG5cdC8vIFBhcnNlIHRoZSBtZXNzYWdlXG5cdGxldCBtZXNzYWdlO1xuXHR0cnkge1xuXHRcdG1lc3NhZ2UgPSBKU09OLnBhcnNlKGluY29taW5nTWVzc2FnZSk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRjb25zdCBlcnJvciA9IGBJbnZhbGlkIEpTT04gcGFzc2VkIHRvIGNhbGxiYWNrOiAke2UubWVzc2FnZX0uIE1lc3NhZ2U6ICR7aW5jb21pbmdNZXNzYWdlfWA7XG5cdFx0cnVudGltZS5Mb2dEZWJ1ZyhlcnJvcik7XG5cdFx0dGhyb3cgbmV3IEVycm9yKGVycm9yKTtcblx0fVxuXHRsZXQgY2FsbGJhY2tJRCA9IG1lc3NhZ2UuY2FsbGJhY2tpZDtcblx0bGV0IGNhbGxiYWNrRGF0YSA9IGNhbGxiYWNrc1tjYWxsYmFja0lEXTtcblx0aWYgKCFjYWxsYmFja0RhdGEpIHtcblx0XHRjb25zdCBlcnJvciA9IGBDYWxsYmFjayAnJHtjYWxsYmFja0lEfScgbm90IHJlZ2lzdGVyZWQhISFgO1xuXHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG5cdFx0dGhyb3cgbmV3IEVycm9yKGVycm9yKTtcblx0fVxuXHRjbGVhclRpbWVvdXQoY2FsbGJhY2tEYXRhLnRpbWVvdXRIYW5kbGUpO1xuXG5cdGRlbGV0ZSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cblx0aWYgKG1lc3NhZ2UuZXJyb3IpIHtcblx0XHRjYWxsYmFja0RhdGEucmVqZWN0KG1lc3NhZ2UuZXJyb3IpO1xuXHR9IGVsc2Uge1xuXHRcdGNhbGxiYWNrRGF0YS5yZXNvbHZlKG1lc3NhZ2UucmVzdWx0KTtcblx0fVxufVxuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX18gICAgXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gICkgXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcblxuLy8gVGhpcyBpcyB3aGVyZSB3ZSBiaW5kIGdvIG1ldGhvZCB3cmFwcGVyc1xud2luZG93LmdvID0ge307XG5cbmV4cG9ydCBmdW5jdGlvbiBTZXRCaW5kaW5ncyhiaW5kaW5nc01hcCkge1xuXHR0cnkge1xuXHRcdGJpbmRpbmdzTWFwID0gSlNPTi5wYXJzZShiaW5kaW5nc01hcCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRjb25zb2xlLmVycm9yKGUpO1xuXHR9XG5cblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXG5cdHdpbmRvdy5nbyA9IHdpbmRvdy5nbyB8fCB7fTtcblxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcblx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXApLmZvckVhY2goKHBhY2thZ2VOYW1lKSA9PiB7XG5cblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXSB8fCB7fTtcblxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXG5cdFx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXBbcGFja2FnZU5hbWVdKS5mb3JFYWNoKChzdHJ1Y3ROYW1lKSA9PiB7XG5cblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxuXHRcdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gfHwge307XG5cblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xuXG5cdFx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV1bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XG5cblx0XHRcdFx0XHQvLyBObyB0aW1lb3V0IGJ5IGRlZmF1bHRcblx0XHRcdFx0XHRsZXQgdGltZW91dCA9IDA7XG5cblx0XHRcdFx0XHQvLyBBY3R1YWwgZnVuY3Rpb25cblx0XHRcdFx0XHRmdW5jdGlvbiBkeW5hbWljKCkge1xuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblx0XHRcdFx0XHRcdHJldHVybiBDYWxsKFtwYWNrYWdlTmFtZSwgc3RydWN0TmFtZSwgbWV0aG9kTmFtZV0uam9pbignLicpLCBhcmdzLCB0aW1lb3V0KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBzZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAobmV3VGltZW91dCkge1xuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxuXHRcdFx0XHRcdGR5bmFtaWMuZ2V0VGltZW91dCA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0aW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRyZXR1cm4gZHluYW1pYztcblx0XHRcdFx0fSgpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkKCkge1xuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZEFwcCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dSJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTeXN0ZW1EZWZhdWx0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVNEVCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TGlnaHRUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBTFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldERhcmtUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBRFQnKTtcbn1cblxuLyoqXG4gKiBQbGFjZSB0aGUgd2luZG93IGluIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0NlbnRlcigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1djJyk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRpdGxlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRpdGxlXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRUaXRsZSh0aXRsZSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1QnICsgdGl0bGUpO1xufVxuXG4vKipcbiAqIE1ha2VzIHRoZSB3aW5kb3cgZ28gZnVsbHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0Z1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXRicpO1xufVxuXG4vKipcbiAqIFJldmVydHMgdGhlIHdpbmRvdyBmcm9tIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbmZ1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXZicpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIGluIGZ1bGwgc2NyZWVuIG1vZGUgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc0Z1bGxzY3JlZW4oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNGdWxsc2NyZWVuXCIpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dzOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0U2l6ZVwiKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNYXhTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWluU2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXejonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG5cblxuLyoqXG4gKiBTZXQgdGhlIHdpbmRvdyBBbHdheXNPblRvcCBvciBub3Qgb24gdG9wXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xuXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVRQOicgKyAoYiA/ICcxJyA6ICcwJykpO1xufVxuXG5cblxuXG4vKipcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gKiBAcGFyYW0ge251bWJlcn0geVxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3A6JyArIHggKyAnOicgKyB5KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt4OiBudW1iZXIsIHk6IG51bWJlcn0+fSBUaGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93R2V0UG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0UG9zXCIpO1xufVxuXG4vKipcbiAqIEhpZGUgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0hpZGUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXSCcpO1xufVxuXG4vKipcbiAqIFNob3cgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1Nob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUycpO1xufVxuXG4vKipcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNYXhpbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dNJyk7XG59XG5cbi8qKlxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdCcpO1xufVxuXG4vKipcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXVScpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1heGltaXNlZCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTWF4aW1pc2VkKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWF4aW1pc2VkXCIpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNaW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dtJyk7XG59XG5cbi8qKlxuICogVW5taW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5taW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d1Jyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbWluaW1pc2VkIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNaW5pbWlzZWQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNNaW5pbWlzZWRcIik7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbm9ybWFsIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNOb3JtYWwoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNOb3JtYWxcIik7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxuICogQHBhcmFtIHtudW1iZXJ9IEcgR3JlZW5cbiAqIEBwYXJhbSB7bnVtYmVyfSBCIEJsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRCYWNrZ3JvdW5kQ29sb3VyKFIsIEcsIEIsIEEpIHtcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3I6JyArIHJnYmEpO1xufVxuXG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cblxuLyoqXG4gKiBHZXRzIHRoZSBhbGwgc2NyZWVucy4gQ2FsbCB0aGlzIGFuZXcgZWFjaCB0aW1lIHlvdSB3YW50IHRvIHJlZnJlc2ggZGF0YSBmcm9tIHRoZSB1bmRlcmx5aW5nIHdpbmRvd2luZyBzeXN0ZW0uXG4gKiBAZXhwb3J0XG4gKiBAdHlwZWRlZiB7aW1wb3J0KCcuLi93cmFwcGVyL3J1bnRpbWUnKS5TY3JlZW59IFNjcmVlblxuICogQHJldHVybiB7UHJvbWlzZTx7U2NyZWVuW119Pn0gVGhlIHNjcmVlbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNjcmVlbkdldEFsbCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpTY3JlZW5HZXRBbGxcIik7XG59XG4iLCAiLyoqXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQnJvd3Nlck9wZW5VUkwodXJsKSB7XG4gIHdpbmRvdy5XYWlsc0ludm9rZSgnQk86JyArIHVybCk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcblxuLyoqXG4gKiBTZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDbGlwYm9hcmRTZXRUZXh0KHRleHQpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRTZXRUZXh0XCIsIFt0ZXh0XSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSB0ZXh0IGNvbnRlbnQgb2YgdGhlIGNsaXBib2FyZFxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8e3N0cmluZ30+fSBUZXh0IGNvbnRlbnQgb2YgdGhlIGNsaXBib2FyZFxuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDbGlwYm9hcmRHZXRUZXh0KCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOkNsaXBib2FyZEdldFRleHRcIik7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuaW1wb3J0ICogYXMgTG9nIGZyb20gJy4vbG9nJztcbmltcG9ydCB7ZXZlbnRMaXN0ZW5lcnMsIEV2ZW50c0VtaXQsIEV2ZW50c05vdGlmeSwgRXZlbnRzT2ZmLCBFdmVudHNPbiwgRXZlbnRzT25jZSwgRXZlbnRzT25NdWx0aXBsZX0gZnJvbSAnLi9ldmVudHMnO1xuaW1wb3J0IHtDYWxsLCBDYWxsYmFjaywgY2FsbGJhY2tzfSBmcm9tICcuL2NhbGxzJztcbmltcG9ydCB7U2V0QmluZGluZ3N9IGZyb20gXCIuL2JpbmRpbmdzXCI7XG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4vd2luZG93XCI7XG5pbXBvcnQgKiBhcyBTY3JlZW4gZnJvbSBcIi4vc2NyZWVuXCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXJcIjtcbmltcG9ydCAqIGFzIENsaXBib2FyZCBmcm9tIFwiLi9jbGlwYm9hcmRcIjtcblxuXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdTJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnSCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XG59XG5cbi8vIFRoZSBKUyBydW50aW1lXG53aW5kb3cucnVudGltZSA9IHtcbiAgICAuLi5Mb2csXG4gICAgLi4uV2luZG93LFxuICAgIC4uLkJyb3dzZXIsXG4gICAgLi4uU2NyZWVuLFxuICAgIC4uLkNsaXBib2FyZCxcbiAgICBFdmVudHNPbixcbiAgICBFdmVudHNPbmNlLFxuICAgIEV2ZW50c09uTXVsdGlwbGUsXG4gICAgRXZlbnRzRW1pdCxcbiAgICBFdmVudHNPZmYsXG4gICAgRW52aXJvbm1lbnQsXG4gICAgU2hvdyxcbiAgICBIaWRlLFxuICAgIFF1aXRcbn07XG5cbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xud2luZG93LndhaWxzID0ge1xuICAgIENhbGxiYWNrLFxuICAgIEV2ZW50c05vdGlmeSxcbiAgICBTZXRCaW5kaW5ncyxcbiAgICBldmVudExpc3RlbmVycyxcbiAgICBjYWxsYmFja3MsXG4gICAgZmxhZ3M6IHtcbiAgICAgICAgZGlzYWJsZVNjcm9sbGJhckRyYWc6IGZhbHNlLFxuICAgICAgICBkaXNhYmxlV2FpbHNEZWZhdWx0Q29udGV4dE1lbnU6IGZhbHNlLFxuICAgICAgICBlbmFibGVSZXNpemU6IGZhbHNlLFxuICAgICAgICBkZWZhdWx0Q3Vyc29yOiBudWxsLFxuICAgICAgICBib3JkZXJUaGlja25lc3M6IDYsXG4gICAgICAgIHNob3VsZERyYWc6IGZhbHNlLFxuICAgICAgICBkZWZlckRyYWdUb01vdXNlTW92ZTogdHJ1ZSxcbiAgICAgICAgY3NzRHJhZ1Byb3BlcnR5OiBcIi0td2FpbHMtZHJhZ2dhYmxlXCIsXG4gICAgICAgIGNzc0RyYWdWYWx1ZTogXCJkcmFnXCIsXG4gICAgfVxufTtcblxuLy8gU2V0IHRoZSBiaW5kaW5nc1xuaWYgKHdpbmRvdy53YWlsc2JpbmRpbmdzKSB7XG4gICAgd2luZG93LndhaWxzLlNldEJpbmRpbmdzKHdpbmRvdy53YWlsc2JpbmRpbmdzKTtcbiAgICBkZWxldGUgd2luZG93LndhaWxzLlNldEJpbmRpbmdzO1xufVxuXG4vLyBUaGlzIGlzIGV2YWx1YXRlZCBhdCBidWlsZCB0aW1lIGluIHBhY2thZ2UuanNvblxuLy8gY29uc3QgZGV2ID0gMDtcbi8vIGNvbnN0IHByb2R1Y3Rpb24gPSAxO1xuaWYgKEVOViA9PT0gMSkge1xuICAgIGRlbGV0ZSB3aW5kb3cud2FpbHNiaW5kaW5ncztcbn1cblxubGV0IGRyYWdUZXN0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgdmFsID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZS50YXJnZXQpLmdldFByb3BlcnR5VmFsdWUod2luZG93LndhaWxzLmZsYWdzLmNzc0RyYWdQcm9wZXJ0eSk7XG4gICAgaWYgKHZhbCkge1xuICAgICAgdmFsID0gdmFsLnRyaW0oKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKHZhbCAhPT0gd2luZG93LndhaWxzLmZsYWdzLmNzc0RyYWdWYWx1ZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGUuYnV0dG9ucyAhPT0gMSkge1xuICAgICAgICAvLyBEbyBub3Qgc3RhcnQgZHJhZ2dpbmcgaWYgbm90IHRoZSBwcmltYXJ5IGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkLlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGUuZGV0YWlsICE9PSAxKSB7XG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBtb3JlIHRoYW4gb25jZSBoYXMgYmVlbiBjbGlja2VkLCBlLmcuIHdoZW4gZG91YmxlIGNsaWNraW5nXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbndpbmRvdy53YWlscy5zZXRDU1NEcmFnUHJvcGVydGllcyA9IGZ1bmN0aW9uIChwcm9wZXJ0eSwgdmFsdWUpIHtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5ID0gcHJvcGVydHk7XG4gICAgd2luZG93LndhaWxzLmZsYWdzLmNzc0RyYWdWYWx1ZSA9IHZhbHVlO1xufVxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgKGUpID0+IHtcblxuICAgIC8vIENoZWNrIGZvciByZXNpemluZ1xuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSkge1xuICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoXCJyZXNpemU6XCIgKyB3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkcmFnVGVzdChlKSkge1xuICAgICAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRpc2FibGVTY3JvbGxiYXJEcmFnKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGNoZWNrcyBmb3IgY2xpY2tzIG9uIHRoZSBzY3JvbGwgYmFyXG4gICAgICAgICAgICBpZiAoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGVmZXJEcmFnVG9Nb3VzZU1vdmUpIHtcbiAgICAgICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKVxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSBmYWxzZTtcbiAgICB9XG59KTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCAoKSA9PiB7XG4gICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSBmYWxzZTtcbn0pO1xuXG5mdW5jdGlvbiBzZXRSZXNpemUoY3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvciB8fCB3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvcjtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSA9IGN1cnNvcjtcbn1cblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnKSB7XG4gICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gZmFsc2U7XG4gICAgICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XG4gICAgICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoXCJkcmFnXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVJlc2l6ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvciA9PSBudWxsKSB7XG4gICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvcjtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcyAmJiB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzKSB7XG4gICAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3IgPSBcInNlLXJlc2l6ZVwiO1xuICAgIH1cbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XG4gICAgbGV0IGxlZnRCb3JkZXIgPSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xuICAgIGxldCB0b3BCb3JkZXIgPSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xuICAgIGxldCBib3R0b21Cb3JkZXIgPSB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xuXG4gICAgLy8gSWYgd2UgYXJlbid0IG9uIGFuIGVkZ2UsIGJ1dCB3ZXJlLCByZXNldCB0aGUgY3Vyc29yIHRvIGRlZmF1bHRcbiAgICBpZiAoIWxlZnRCb3JkZXIgJiYgIXJpZ2h0Qm9yZGVyICYmICF0b3BCb3JkZXIgJiYgIWJvdHRvbUJvcmRlciAmJiB3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHNldFJlc2l6ZSgpO1xuICAgIH0gZWxzZSBpZiAocmlnaHRCb3JkZXIgJiYgYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzZS1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdEJvcmRlciAmJiBib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInN3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyICYmIHRvcEJvcmRlcikgc2V0UmVzaXplKFwibnctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHRvcEJvcmRlciAmJiByaWdodEJvcmRlcikgc2V0UmVzaXplKFwibmUtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIpIHNldFJlc2l6ZShcInctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHRvcEJvcmRlcikgc2V0UmVzaXplKFwibi1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAoYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChyaWdodEJvcmRlcikgc2V0UmVzaXplKFwiZS1yZXNpemVcIik7XG5cbn0pO1xuXG4vLyBTZXR1cCBjb250ZXh0IG1lbnUgaG9va1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRpc2FibGVXYWlsc0RlZmF1bHRDb250ZXh0TWVudSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxufSk7XG5cbndpbmRvdy5XYWlsc0ludm9rZShcInJ1bnRpbWU6cmVhZHlcIik7Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7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QSxFQUNwQztBQUVBLFNBQU8saUJBQWlCLGFBQWEsU0FBVSxHQUFHO0FBQzlDLFFBQUksT0FBTyxNQUFNLE1BQU0sWUFBWTtBQUMvQixhQUFPLE1BQU0sTUFBTSxhQUFhO0FBQ2hDLFVBQUksZUFBZSxFQUFFLFlBQVksU0FBWSxFQUFFLFVBQVUsRUFBRTtBQUMzRCxVQUFJLGVBQWUsR0FBRztBQUNsQixlQUFPLFlBQVksTUFBTTtBQUN6QjtBQUFBLE1BQ0o7QUFBQSxJQUNKO0FBQ0EsUUFBSSxDQUFDLE9BQU8sTUFBTSxNQUFNLGNBQWM7QUFDbEM7QUFBQSxJQUNKO0FBQ0EsUUFBSSxPQUFPLE1BQU0sTUFBTSxpQkFBaUIsTUFBTTtBQUMxQyxhQUFPLE1BQU0sTUFBTSxnQkFBZ0IsU0FBUyxnQkFBZ0IsTUFBTTtBQUFBLElBQ3RFO0FBQ0EsUUFBSSxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLG1CQUFtQixPQUFPLGNBQWMsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLGlCQUFpQjtBQUMzSSxlQUFTLGdCQUFnQixNQUFNLFNBQVM7QUFBQSxJQUM1QztBQUNBLFFBQUksY0FBYyxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQ3JFLFFBQUksYUFBYSxFQUFFLFVBQVUsT0FBTyxNQUFNLE1BQU07QUFDaEQsUUFBSSxZQUFZLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUMvQyxRQUFJLGVBQWUsT0FBTyxjQUFjLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUd2RSxRQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLE9BQU8sTUFBTSxNQUFNLGVBQWUsUUFBVztBQUMzRyxnQkFBVTtBQUFBLElBQ2QsV0FBVyxlQUFlO0FBQWMsZ0JBQVUsV0FBVztBQUFBLGFBQ3BELGNBQWM7QUFBYyxnQkFBVSxXQUFXO0FBQUEsYUFDakQsY0FBYztBQUFXLGdCQUFVLFdBQVc7QUFBQSxhQUM5QyxhQUFhO0FBQWEsZ0JBQVUsV0FBVztBQUFBLGFBQy9DO0FBQVksZ0JBQVUsVUFBVTtBQUFBLGFBQ2hDO0FBQVcsZ0JBQVUsVUFBVTtBQUFBLGFBQy9CO0FBQWMsZ0JBQVUsVUFBVTtBQUFBLGFBQ2xDO0FBQWEsZ0JBQVUsVUFBVTtBQUFBLEVBRTlDLENBQUM7QUFHRCxTQUFPLGlCQUFpQixlQUFlLFNBQVUsR0FBRztBQUNoRCxRQUFJLE9BQU8sTUFBTSxNQUFNLGdDQUFnQztBQUNuRCxRQUFFLGVBQWU7QUFBQSxJQUNyQjtBQUFBLEVBQ0osQ0FBQztBQUVELFNBQU8sWUFBWSxlQUFlOyIsCiAgIm5hbWVzIjogWyJldmVudE5hbWUiXQp9Cg==
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.go b/v2/internal/frontend/runtime/runtime_prod_desktop.go
index 4fd8aaa58..7336f0102 100644
--- a/v2/internal/frontend/runtime/runtime_prod_desktop.go
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.go
@@ -1,4 +1,4 @@
-//go:build production
+//go:build production && !debug
package runtime
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.js b/v2/internal/frontend/runtime/runtime_prod_desktop.js
index 23b66953b..9b2f39ff0 100644
--- a/v2/internal/frontend/runtime/runtime_prod_desktop.js
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.js
@@ -1 +1 @@
-(()=>{var L=Object.defineProperty;var c=(e,n)=>{for(var o in n)L(e,o,{get:n[o],enumerable:!0})};var m={};c(m,{LogDebug:()=>M,LogError:()=>A,LogFatal:()=>H,LogInfo:()=>P,LogLevel:()=>J,LogPrint:()=>R,LogTrace:()=>z,LogWarning:()=>B,SetLogLevel:()=>G});function d(e,n){window.WailsInvoke("L"+e+n)}function z(e){d("T",e)}function R(e){d("P",e)}function M(e){d("D",e)}function P(e){d("I",e)}function B(e){d("W",e)}function A(e){d("E",e)}function H(e){d("F",e)}function G(e){d("S",e)}var J={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var v=class{constructor(n,o,i){this.eventName=n,this.maxCallbacks=i||-1,this.Callback=t=>(o.apply(null,t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},l={};function p(e,n,o){l[e]=l[e]||[];let i=new v(e,n,o);return l[e].push(i),()=>F(i)}function b(e,n){return p(e,n,-1)}function E(e,n){return p(e,n,1)}function S(e){let n=e.name;if(l[n]){let o=l[n].slice();for(let i=l[n].length-1;i>=0;i-=1){let t=l[n][i],r=e.data;t.Callback(r)&&o.splice(i,1)}o.length===0?g(n):l[n]=o}}function y(e){let n;try{n=JSON.parse(e)}catch{let i="Invalid JSON passed to Notify: "+e;throw new Error(i)}S(n)}function C(e){let n={name:e,data:[].slice.apply(arguments).slice(1)};S(n),window.WailsInvoke("EE"+JSON.stringify(n))}function g(e){delete l[e],window.WailsInvoke("EX"+e)}function D(e,...n){g(e),n.length>0&&n.forEach(o=>{g(o)})}function F(e){let n=e.eventName;l[n]=l[n].filter(o=>o!==e),l[n].length===0&&g(n)}var f={};function U(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}function j(){return Math.random()*9007199254740991}var W;window.crypto?W=U:W=j;function s(e,n,o){return o==null&&(o=0),new Promise(function(i,t){var r;do r=e+"-"+W();while(f[r]);var a;o>0&&(a=setTimeout(function(){t(Error("Call to "+e+" timed out. Request ID: "+r))},o)),f[r]={timeoutHandle:a,reject:t,resolve:i};try{let u={name:e,args:n,callbackID:r};window.WailsInvoke("C"+JSON.stringify(u))}catch(u){console.error(u)}})}window.ObfuscatedCall=(e,n,o)=>(o==null&&(o=0),new Promise(function(i,t){var r;do r=e+"-"+W();while(f[r]);var a;o>0&&(a=setTimeout(function(){t(Error("Call to method "+e+" timed out. Request ID: "+r))},o)),f[r]={timeoutHandle:a,reject:t,resolve:i};try{let u={id:e,args:n,callbackID:r};window.WailsInvoke("c"+JSON.stringify(u))}catch(u){console.error(u)}}));function T(e){let n;try{n=JSON.parse(e)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let o=n.callbackid,i=f[o];if(!i){let t=`Callback '${o}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete f[o],n.error?i.reject(n.error):i.resolve(n.result)}window.go={};function O(e){try{e=JSON.parse(e)}catch(n){console.error(n)}window.go=window.go||{},Object.keys(e).forEach(n=>{window.go[n]=window.go[n]||{},Object.keys(e[n]).forEach(o=>{window.go[n][o]=window.go[n][o]||{},Object.keys(e[n][o]).forEach(i=>{window.go[n][o][i]=function(){let t=0;function r(){let a=[].slice.call(arguments);return s([n,o,i].join("."),a,t)}return r.setTimeout=function(a){t=a},r.getTimeout=function(){return t},r}()})})})}var x={};c(x,{WindowCenter:()=>q,WindowFullscreen:()=>Z,WindowGetPosition:()=>se,WindowGetSize:()=>ne,WindowHide:()=>le,WindowIsFullscreen:()=>_,WindowIsMaximised:()=>ue,WindowIsMinimised:()=>pe,WindowIsNormal:()=>We,WindowMaximise:()=>we,WindowMinimise:()=>ce,WindowReload:()=>N,WindowReloadApp:()=>V,WindowSetAlwaysOnTop:()=>te,WindowSetBackgroundColour:()=>me,WindowSetDarkTheme:()=>$,WindowSetLightTheme:()=>Y,WindowSetMaxSize:()=>oe,WindowSetMinSize:()=>ie,WindowSetPosition:()=>re,WindowSetSize:()=>ee,WindowSetSystemDefaultTheme:()=>X,WindowSetTitle:()=>Q,WindowShow:()=>ae,WindowToggleMaximise:()=>de,WindowUnfullscreen:()=>K,WindowUnmaximise:()=>fe,WindowUnminimise:()=>ge});function N(){window.location.reload()}function V(){window.WailsInvoke("WR")}function X(){window.WailsInvoke("WASDT")}function Y(){window.WailsInvoke("WALT")}function $(){window.WailsInvoke("WADT")}function q(){window.WailsInvoke("Wc")}function Q(e){window.WailsInvoke("WT"+e)}function Z(){window.WailsInvoke("WF")}function K(){window.WailsInvoke("Wf")}function _(){return s(":wails:WindowIsFullscreen")}function ee(e,n){window.WailsInvoke("Ws:"+e+":"+n)}function ne(){return s(":wails:WindowGetSize")}function oe(e,n){window.WailsInvoke("WZ:"+e+":"+n)}function ie(e,n){window.WailsInvoke("Wz:"+e+":"+n)}function te(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function re(e,n){window.WailsInvoke("Wp:"+e+":"+n)}function se(){return s(":wails:WindowGetPos")}function le(){window.WailsInvoke("WH")}function ae(){window.WailsInvoke("WS")}function we(){window.WailsInvoke("WM")}function de(){window.WailsInvoke("Wt")}function fe(){window.WailsInvoke("WU")}function ue(){return s(":wails:WindowIsMaximised")}function ce(){window.WailsInvoke("Wm")}function ge(){window.WailsInvoke("Wu")}function pe(){return s(":wails:WindowIsMinimised")}function We(){return s(":wails:WindowIsNormal")}function me(e,n,o,i){let t=JSON.stringify({r:e||0,g:n||0,b:o||0,a:i||255});window.WailsInvoke("Wr:"+t)}var k={};c(k,{ScreenGetAll:()=>ve});function ve(){return s(":wails:ScreenGetAll")}var h={};c(h,{BrowserOpenURL:()=>xe});function xe(e){window.WailsInvoke("BO:"+e)}var I={};c(I,{ClipboardGetText:()=>he,ClipboardSetText:()=>ke});function ke(e){return s(":wails:ClipboardSetText",[e])}function he(){return s(":wails:ClipboardGetText")}function Ie(){window.WailsInvoke("Q")}function be(){window.WailsInvoke("S")}function Ee(){window.WailsInvoke("H")}function Se(){return s(":wails:Environment")}window.runtime={...m,...x,...h,...k,...I,EventsOn:b,EventsOnce:E,EventsOnMultiple:p,EventsEmit:C,EventsOff:D,Environment:Se,Show:be,Hide:Ee,Quit:Ie};window.wails={Callback:T,EventsNotify:y,SetBindings:O,eventListeners:l,callbacks:f,flags:{disableScrollbarDrag:!1,disableWailsDefaultContextMenu:!1,enableResize:!1,defaultCursor:null,borderThickness:6,shouldDrag:!1,deferDragToMouseMove:!0,cssDragProperty:"--wails-draggable",cssDragValue:"drag"}};window.wailsbindings&&(window.wails.SetBindings(window.wailsbindings),delete window.wails.SetBindings);delete window.wailsbindings;var ye=function(e){var n=window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty);return n&&(n=n.trim()),!(n!==window.wails.flags.cssDragValue||e.buttons!==1||e.detail!==1)};window.wails.setCSSDragProperties=function(e,n){window.wails.flags.cssDragProperty=e,window.wails.flags.cssDragValue=n};window.addEventListener("mousedown",e=>{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}if(ye(e)){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))return;window.wails.flags.deferDragToMouseMove?window.wails.flags.shouldDrag=!0:(e.preventDefault(),window.WailsInvoke("drag"));return}else window.wails.flags.shouldDrag=!1});window.addEventListener("mouseup",()=>{window.wails.flags.shouldDrag=!1});function w(e){document.documentElement.style.cursor=e||window.wails.flags.defaultCursor,window.wails.flags.resizeEdge=e}window.addEventListener("mousemove",function(e){if(window.wails.flags.shouldDrag&&(window.wails.flags.shouldDrag=!1,(e.buttons!==void 0?e.buttons:e.which)>0)){window.WailsInvoke("drag");return}if(!window.wails.flags.enableResize)return;window.wails.flags.defaultCursor==null&&(window.wails.flags.defaultCursor=document.documentElement.style.cursor),window.outerWidth-e.clientX{var P=Object.defineProperty;var c=(e,n)=>{for(var o in n)P(e,o,{get:n[o],enumerable:!0})};var x={};c(x,{LogDebug:()=>G,LogError:()=>F,LogFatal:()=>J,LogInfo:()=>H,LogLevel:()=>j,LogPrint:()=>B,LogTrace:()=>A,LogWarning:()=>U,SetLogLevel:()=>N});function f(e,n){window.WailsInvoke("L"+e+n)}function A(e){f("T",e)}function B(e){f("P",e)}function G(e){f("D",e)}function H(e){f("I",e)}function U(e){f("W",e)}function F(e){f("E",e)}function J(e){f("F",e)}function N(e){f("S",e)}var j={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var v=class{constructor(n,o,t){this.eventName=n,this.maxCallbacks=t||-1,this.Callback=i=>(o.apply(null,i),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},a={};function p(e,n,o){a[e]=a[e]||[];let t=new v(e,n,o);return a[e].push(t),()=>V(t)}function y(e,n){return p(e,n,-1)}function C(e,n){return p(e,n,1)}function D(e){let n=e.name;if(a[n]){let o=a[n].slice();for(let t=a[n].length-1;t>=0;t-=1){let i=a[n][t],r=e.data;i.Callback(r)&&o.splice(t,1)}o.length===0?g(n):a[n]=o}}function T(e){let n;try{n=JSON.parse(e)}catch{let t="Invalid JSON passed to Notify: "+e;throw new Error(t)}D(n)}function O(e){let n={name:e,data:[].slice.apply(arguments).slice(1)};D(n),window.WailsInvoke("EE"+JSON.stringify(n))}function g(e){delete a[e],window.WailsInvoke("EX"+e)}function L(e,...n){g(e),n.length>0&&n.forEach(o=>{g(o)})}function V(e){let n=e.eventName;a[n]=a[n].filter(o=>o!==e),a[n].length===0&&g(n)}var u={};function X(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}function Y(){return Math.random()*9007199254740991}var W;window.crypto?W=X:W=Y;function s(e,n,o){return o==null&&(o=0),new Promise(function(t,i){var r;do r=e+"-"+W();while(u[r]);var l;o>0&&(l=setTimeout(function(){i(Error("Call to "+e+" timed out. Request ID: "+r))},o)),u[r]={timeoutHandle:l,reject:i,resolve:t};try{let d={name:e,args:n,callbackID:r};window.WailsInvoke("C"+JSON.stringify(d))}catch(d){console.error(d)}})}window.ObfuscatedCall=(e,n,o)=>(o==null&&(o=0),new Promise(function(t,i){var r;do r=e+"-"+W();while(u[r]);var l;o>0&&(l=setTimeout(function(){i(Error("Call to method "+e+" timed out. Request ID: "+r))},o)),u[r]={timeoutHandle:l,reject:i,resolve:t};try{let d={id:e,args:n,callbackID:r};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function z(e){let n;try{n=JSON.parse(e)}catch(i){let r=`Invalid JSON passed to callback: ${i.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let o=n.callbackid,t=u[o];if(!t){let i=`Callback '${o}' not registered!!!`;throw console.error(i),new Error(i)}clearTimeout(t.timeoutHandle),delete u[o],n.error?t.reject(n.error):t.resolve(n.result)}window.go={};function M(e){try{e=JSON.parse(e)}catch(n){console.error(n)}window.go=window.go||{},Object.keys(e).forEach(n=>{window.go[n]=window.go[n]||{},Object.keys(e[n]).forEach(o=>{window.go[n][o]=window.go[n][o]||{},Object.keys(e[n][o]).forEach(t=>{window.go[n][o][t]=function(){let i=0;function r(){let l=[].slice.call(arguments);return s([n,o,t].join("."),l,i)}return r.setTimeout=function(l){i=l},r.getTimeout=function(){return i},r}()})})})}var h={};c(h,{WindowCenter:()=>_,WindowFullscreen:()=>ne,WindowGetPosition:()=>de,WindowGetSize:()=>re,WindowHide:()=>fe,WindowIsFullscreen:()=>te,WindowIsMaximised:()=>We,WindowIsMinimised:()=>ve,WindowIsNormal:()=>he,WindowMaximise:()=>ce,WindowMinimise:()=>me,WindowReload:()=>$,WindowReloadApp:()=>q,WindowSetAlwaysOnTop:()=>ae,WindowSetBackgroundColour:()=>ke,WindowSetDarkTheme:()=>K,WindowSetLightTheme:()=>Z,WindowSetMaxSize:()=>se,WindowSetMinSize:()=>le,WindowSetPosition:()=>we,WindowSetSize:()=>ie,WindowSetSystemDefaultTheme:()=>Q,WindowSetTitle:()=>ee,WindowShow:()=>ue,WindowToggleMaximise:()=>ge,WindowUnfullscreen:()=>oe,WindowUnmaximise:()=>pe,WindowUnminimise:()=>xe});function $(){window.location.reload()}function q(){window.WailsInvoke("WR")}function Q(){window.WailsInvoke("WASDT")}function Z(){window.WailsInvoke("WALT")}function K(){window.WailsInvoke("WADT")}function _(){window.WailsInvoke("Wc")}function ee(e){window.WailsInvoke("WT"+e)}function ne(){window.WailsInvoke("WF")}function oe(){window.WailsInvoke("Wf")}function te(){return s(":wails:WindowIsFullscreen")}function ie(e,n){window.WailsInvoke("Ws:"+e+":"+n)}function re(){return s(":wails:WindowGetSize")}function se(e,n){window.WailsInvoke("WZ:"+e+":"+n)}function le(e,n){window.WailsInvoke("Wz:"+e+":"+n)}function ae(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function we(e,n){window.WailsInvoke("Wp:"+e+":"+n)}function de(){return s(":wails:WindowGetPos")}function fe(){window.WailsInvoke("WH")}function ue(){window.WailsInvoke("WS")}function ce(){window.WailsInvoke("WM")}function ge(){window.WailsInvoke("Wt")}function pe(){window.WailsInvoke("WU")}function We(){return s(":wails:WindowIsMaximised")}function me(){window.WailsInvoke("Wm")}function xe(){window.WailsInvoke("Wu")}function ve(){return s(":wails:WindowIsMinimised")}function he(){return s(":wails:WindowIsNormal")}function ke(e,n,o,t){let i=JSON.stringify({r:e||0,g:n||0,b:o||0,a:t||255});window.WailsInvoke("Wr:"+i)}var k={};c(k,{ScreenGetAll:()=>Ie});function Ie(){return s(":wails:ScreenGetAll")}var I={};c(I,{BrowserOpenURL:()=>be});function be(e){window.WailsInvoke("BO:"+e)}var b={};c(b,{ClipboardGetText:()=>Ee,ClipboardSetText:()=>Se});function Se(e){return s(":wails:ClipboardSetText",[e])}function Ee(){return s(":wails:ClipboardGetText")}function R(e){let n=e.target;switch(window.getComputedStyle(n).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(n.isContentEditable)return;let i=window.getSelection(),r=i.toString().length>0;if(r)for(let l=0;l{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}if(Le(e)){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))return;window.wails.flags.deferDragToMouseMove?window.wails.flags.shouldDrag=!0:(e.preventDefault(),window.WailsInvoke("drag"));return}else window.wails.flags.shouldDrag=!1});window.addEventListener("mouseup",()=>{window.wails.flags.shouldDrag=!1});function w(e){document.documentElement.style.cursor=e||window.wails.flags.defaultCursor,window.wails.flags.resizeEdge=e}window.addEventListener("mousemove",function(e){if(window.wails.flags.shouldDrag&&(window.wails.flags.shouldDrag=!1,(e.buttons!==void 0?e.buttons:e.which)>0)){window.WailsInvoke("drag");return}if(!window.wails.flags.enableResize)return;window.wails.flags.defaultCursor==null&&(window.wails.flags.defaultCursor=document.documentElement.style.cursor),window.outerWidth-e.clientX
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html
index e2db01c7d..fbe3eb240 100644
--- a/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/lit/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html
index e88b655ef..3dd212f2d 100644
--- a/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/svelte-ts/frontend/index.tmpl.html
@@ -3,7 +3,6 @@
-
{{.ProjectName}}
diff --git a/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html
index 5c0949b5e..cc259435b 100644
--- a/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/vue-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html b/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html
index b3d4289c3..d45b7a8c4 100644
--- a/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html
+++ b/v2/pkg/templates/generate/assets/vue/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html b/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html
index 4944992b5..febcb76cb 100644
--- a/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/lit-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts b/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts
index 27fd71e45..af4e9ce20 100644
--- a/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts
+++ b/v2/pkg/templates/templates/lit-ts/frontend/src/my-element.ts
@@ -2,6 +2,7 @@ import {css, html, LitElement} from 'lit'
import logo from './assets/images/logo-universal.png'
import {Greet} from "../wailsjs/go/main/App";
import {customElement, property} from 'lit/decorators.js'
+import './style.css';
/**
* An example element.
diff --git a/v2/pkg/templates/templates/lit/frontend/index.tmpl.html b/v2/pkg/templates/templates/lit/frontend/index.tmpl.html
index e2db01c7d..fbe3eb240 100644
--- a/v2/pkg/templates/templates/lit/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/lit/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/lit/frontend/src/my-element.js b/v2/pkg/templates/templates/lit/frontend/src/my-element.js
index ed65e2225..017632c09 100644
--- a/v2/pkg/templates/templates/lit/frontend/src/my-element.js
+++ b/v2/pkg/templates/templates/lit/frontend/src/my-element.js
@@ -1,6 +1,7 @@
import {css, html, LitElement} from 'lit'
import logo from './assets/images/logo-universal.png'
import {Greet} from "../wailsjs/go/main/App";
+import './style.css';
/**
* An example element.
diff --git a/v2/pkg/templates/templates/plain/frontend/src/main.js b/v2/pkg/templates/templates/plain/frontend/src/main.js
index 3346d59ff..e4945441d 100644
--- a/v2/pkg/templates/templates/plain/frontend/src/main.js
+++ b/v2/pkg/templates/templates/plain/frontend/src/main.js
@@ -1,6 +1,7 @@
// Get input + focus
let nameElement = document.getElementById("name");
nameElement.focus();
+import './main.css';
// Setup the greet function
window.greet = function () {
diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html b/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html
index e88b655ef..3dd212f2d 100644
--- a/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/svelte-ts/frontend/index.tmpl.html
@@ -3,7 +3,6 @@
-
{{.ProjectName}}
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html b/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html
index 5c0949b5e..cc259435b 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/vue-ts/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts b/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts
index e57db5948..f9754fe19 100644
--- a/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts
+++ b/v2/pkg/templates/templates/vue-ts/frontend/src/main.ts
@@ -1,4 +1,5 @@
import {createApp} from 'vue'
import App from './App.vue'
+import './style.css';
createApp(App).mount('#app')
diff --git a/v2/pkg/templates/templates/vue/frontend/index.tmpl.html b/v2/pkg/templates/templates/vue/frontend/index.tmpl.html
index b3d4289c3..d45b7a8c4 100644
--- a/v2/pkg/templates/templates/vue/frontend/index.tmpl.html
+++ b/v2/pkg/templates/templates/vue/frontend/index.tmpl.html
@@ -4,7 +4,6 @@
{{.ProjectName}}
-
diff --git a/v2/pkg/templates/templates/vue/frontend/src/main.js b/v2/pkg/templates/templates/vue/frontend/src/main.js
index e57db5948..f9754fe19 100644
--- a/v2/pkg/templates/templates/vue/frontend/src/main.js
+++ b/v2/pkg/templates/templates/vue/frontend/src/main.js
@@ -1,4 +1,5 @@
import {createApp} from 'vue'
import App from './App.vue'
+import './style.css';
createApp(App).mount('#app')
diff --git a/website/docs/community/templates.mdx b/website/docs/community/templates.mdx
index e73bbec2b..3543cbe9c 100644
--- a/website/docs/community/templates.mdx
+++ b/website/docs/community/templates.mdx
@@ -41,6 +41,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript
- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS
+- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui
## Svelte
diff --git a/website/docs/guides/application-development.mdx b/website/docs/guides/application-development.mdx
index f8074d150..9d04fe917 100644
--- a/website/docs/guides/application-development.mdx
+++ b/website/docs/guides/application-development.mdx
@@ -219,8 +219,33 @@ be saved to your project config and become the default.
Some frameworks come with their own live-reloading server, however they will not be able to take advantage of the Wails
Go bindings. In this scenario, it is best to run a watcher script that rebuilds the project into the build directory, which
Wails will be watching. For an example, see the default svelte template that uses [rollup](https://rollupjs.org/guide/en/).
-For [create-react-app](https://create-react-app.dev/), it's possible to use
-[this script](https://gist.github.com/int128/e0cdec598c5b3db728ff35758abdbafd) to achieve a similar result.
+
+### Create React App
+
+The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration
+needs to be added to your `wails.json`:
+
+```json
+ "frontend:dev:watcher": "yarn start",
+ "frontend:dev:serverUrl": "http://localhost:3000",
+```
+
+The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then
+instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the
+`index.html` needs to be updated with the following:
+
+```html
+
+
+
+
+
+```
+
+This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring
+the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled.
+Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward
+debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step.
## Go Module
diff --git a/website/docs/guides/sveltekit.mdx b/website/docs/guides/sveltekit.mdx
new file mode 100644
index 000000000..3f82eb813
--- /dev/null
+++ b/website/docs/guides/sveltekit.mdx
@@ -0,0 +1,133 @@
+# SvelteKit
+
+This guide will go into:
+1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit.
+2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding.
+3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes.
+
+## 1. Minimal Installation Steps
+
+##### Install Wails for Svelte.
+- `wails init -n myapp -t svelte`
+
+##### Delete the svelte frontend.
+- Navigate into your newly created myapp folder.
+- Delete the folder named "frontend"
+
+##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts.
+- `npm create svelte@latest frontend`
+
+##### Modify wails.json.
+- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear.
+- Change your package manager frontend here if not using npm.
+
+##### Modify main.go.
+- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build`
+
+##### Install/remove dependencies using your favorite package manager.
+- Navigate into your "frontend" folder.
+- `npm i`
+- `npm uninstall @sveltejs/adapter-auto`
+- `npm i -D @sveltejs/adapter-static`
+
+##### Change adapter in svelte.config.js
+- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';`
+
+##### Put SvelteKit into SPA mode with prerendering.
+- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js.
+- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false`
+
+##### Test installation.
+- Navigate back into the Wails project root (one directory up).
+- run `wails dev`
+- If the application doesn't run please check through the previous steps.
+
+## 2. Install Script
+
+##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer.
+
+- Create a file sveltekit-wails.sh
+- Copy the below code into the new file then save it.
+- Make it executable with `chmod +x sveltekit-wails.sh`
+- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding.
+- Example usage: `./sveltekit-wails.sh pnpm newapp brand`
+
+##### sveltekit-wails.sh:
+```
+manager=$1
+project=$2
+brand=$3
+wails init -n $project -t svelte
+cd $project
+sed -i "s|npm|$manager|g" wails.json
+sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json
+sed -i "s|all:frontend/dist|all:frontend/build|" main.go
+if [[ -n $brand ]]; then
+ mv frontend/src/App.svelte +page.svelte
+ sed -i "s|'./assets|'\$lib/assets|" +page.svelte
+ sed -i "s|'../wails|'\$lib/wails|" +page.svelte
+ mv frontend/src/assets .
+fi
+rm -r frontend
+$manager create svelte@latest frontend
+if [[ -n $brand ]]; then
+ mv +page.svelte frontend/src/routes/+page.svelte
+ mkdir frontend/src/lib
+ mv assets frontend/src/lib/
+fi
+cd frontend
+$manager i
+$manager uninstall @sveltejs/adapter-auto
+$manager i -D @sveltejs/adapter-static
+echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts
+sed -i "s|-auto';|-static';|" svelte.config.js
+cd ..
+wails dev
+```
+
+## 3. Important Notes
+
+##### Server files will cause build failures.
+- +layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered.
+
+##### The Wails runtime unloads with full page navigations!
+- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this.
+- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation.
+- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html
+```
+
+...
+
+
+
+...
+
+```
+See https://wails.io/docs/guides/frontend for more information.
+
+##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte.
+- +page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data
+- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation.
+
+##### Error Handling
+- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors
+- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file.
+```
+import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime'
+export async function handleError() {
+ WindowReloadApp()
+}
+```
+
+##### Using Forms and handling functions
+- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `