From 123ee5021a8a0b28cd309b659e31584eebc3a087 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 14:54:22 +0100 Subject: [PATCH 01/11] refactor: remove unnecessary async/await --- src/ffi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ffi.ts b/src/ffi.ts index ea7799b..051f402 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -23,8 +23,8 @@ export function encodeCString(value: string) { * * @returns true if it exists, false if it doesn't */ -async function checkForWebView2Loader(): Promise { - return await Deno.stat("./WebView2Loader.dll").then( +function checkForWebView2Loader(): Promise { + return Deno.stat("./WebView2Loader.dll").then( () => true, (e) => e instanceof Deno.errors.NotFound ? false : true, ); From b407bba28a4a36bcfd2c51686bebef4eea0f0e95 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 15:37:41 +0100 Subject: [PATCH 02/11] refactor: change dll caching method --- src/ffi.ts | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/ffi.ts b/src/ffi.ts index 051f402..ad25467 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -48,24 +48,18 @@ export const instances: Webview[] = []; * * Does not need to be run on non-windows platforms, but that is subject to change. */ -export async function preload() { - if (preloaded) return; +if (Deno.build.os === 'windows') { + //Download and cache `./WebView2Loader.dll` + const { default: dll } = await import(`https://ejm.sh/${url}/WebView2Loader.dll?.json`, { assert: { type: 'json' } }) as { default: { b64: string } }; + const dataUrl = `data:application/octet-stream;base64,${dll.b64}`; + const webview2loader = (await fetch(dataUrl)).body; - if (Deno.build.os === "windows") { - if (await checkForWebView2Loader()) { - await Deno.remove("./WebView2Loader.dll"); - } - - const webview2loader = await download({ - url: `${url}/WebView2Loader.dll`, - cache, - }); - await Deno.copyFile(webview2loader, "./WebView2Loader.dll"); - - self.addEventListener("unload", unload); - } + //Overwrite local dll with the version specified in "url" + const fsFile = await Deno.open('./WebView2Loader.dll', { create: true, write: true }); + await webview2loader?.pipeTo(fsFile.writable); + fsFile.close(); - preloaded = true; + self.addEventListener("unload", unload); } /** From 5f5fe180c62621078d2a43f536cc3ba54026a6cc Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 15:50:16 +0100 Subject: [PATCH 03/11] chore: prevent multple file remove --- src/ffi.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ffi.ts b/src/ffi.ts index ad25467..01b19df 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -74,7 +74,11 @@ export function unload() { } lib.close(); if (Deno.build.os === "windows") { - Deno.removeSync("./WebView2Loader.dll"); + //Try to remove "./WebView2Loader.dll" if it exists + Deno.remove("./WebView2Loader.dll").catch((e) => { + if (e instanceof Deno.errors.NotFound) return; + throw e; + }); } } From 02aef134bf798035a1263edb66b046545b330a91 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 15:56:17 +0100 Subject: [PATCH 04/11] chore: remove loader checker --- src/ffi.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/ffi.ts b/src/ffi.ts index 01b19df..bece2b0 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -18,21 +18,6 @@ export function encodeCString(value: string) { return encoder.encode(value + "\0"); } -/** - * Checks for the existence of `./WebView2Loader.dll` for running on Windows. - * - * @returns true if it exists, false if it doesn't - */ -function checkForWebView2Loader(): Promise { - return Deno.stat("./WebView2Loader.dll").then( - () => true, - (e) => e instanceof Deno.errors.NotFound ? false : true, - ); -} - -// make sure we don't preload twice -let preloaded = false; - /** * All active webview instances. This is internally used for automatically * destroying all instances once {@link unload} is called. From c15b5c6cc3935ed472e5068634e3a4dcce7abfbe Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 16:00:21 +0100 Subject: [PATCH 05/11] chore: remove plug/download due to refactoring --- deps.ts | 2 +- src/ffi.ts | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/deps.ts b/deps.ts index 663b8c2..dc4140b 100644 --- a/deps.ts +++ b/deps.ts @@ -1 +1 @@ -export { dlopen, download } from "https://deno.land/x/plug@1.0.0-rc.3/mod.ts"; +export { dlopen } from "https://deno.land/x/plug@1.0.0-rc.3/mod.ts"; diff --git a/src/ffi.ts b/src/ffi.ts index bece2b0..ece9bba 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -1,4 +1,4 @@ -import { dlopen, download } from "../deps.ts"; +import { dlopen } from "../deps.ts"; import { Webview } from "./webview.ts"; const version = "0.7.3"; @@ -67,17 +67,6 @@ export function unload() { } } -// Automatically run the preload if we're on windows and on the main thread. -if (Deno.build.os === "windows") { - if ((self as never)["window"]) { - await preload(); - } else if (!await checkForWebView2Loader()) { - throw new Error( - "WebView2Loader.dll does not exist! Make sure to run preload() from the main thread.", - ); - } -} - export const lib = await dlopen( { name: "webview", From 87e588afaecdd42de612cb63348afe63c7716ae1 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 16:04:00 +0100 Subject: [PATCH 06/11] chore: remove old exports --- mod.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod.ts b/mod.ts index 54b55d0..1bdaf64 100644 --- a/mod.ts +++ b/mod.ts @@ -1,2 +1,2 @@ export * from "./src/webview.ts"; -export { preload, unload } from "./src/ffi.ts"; +export { unload } from "./src/ffi.ts"; From 3f62307d33eaeee1ff567b915b5c1eeb071de4d0 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 16:12:14 +0100 Subject: [PATCH 07/11] fix: prevent memory leaks on promise errors --- src/ffi.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ffi.ts b/src/ffi.ts index ece9bba..a0da654 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -139,3 +139,9 @@ export const lib = await dlopen( }, } as const, ); + +// Prevent memory leaks on uncaught promises errors +addEventListener('unhandledrejection', (e) => { + unload(); + throw e; +}) From 62c1480a4edc6acbcbd6c05c4d77d8ea131b0c64 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 16:31:02 +0100 Subject: [PATCH 08/11] fix: update plugin url version --- src/ffi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ffi.ts b/src/ffi.ts index a0da654..24e0701 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -1,7 +1,7 @@ import { dlopen } from "../deps.ts"; import { Webview } from "./webview.ts"; -const version = "0.7.3"; +const version = "0.7.4"; const cache = Deno.env.get("PLUGIN_URL") === undefined ? "use" : "reloadAll"; const url = Deno.env.get("PLUGIN_URL") ?? `https://github.com/webview/webview_deno/releases/download/${version}/`; From f6633deb30894923876931addb351fdd323d5916 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 17:16:31 +0100 Subject: [PATCH 09/11] fix: remove manual file close --- src/ffi.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ffi.ts b/src/ffi.ts index 24e0701..9f436d0 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -41,8 +41,7 @@ if (Deno.build.os === 'windows') { //Overwrite local dll with the version specified in "url" const fsFile = await Deno.open('./WebView2Loader.dll', { create: true, write: true }); - await webview2loader?.pipeTo(fsFile.writable); - fsFile.close(); + await webview2loader?.pipeTo(fsFile.writable); //fsFile is closed by the stream self.addEventListener("unload", unload); } From d1085db8316f5cff0b81543f477b8b2787dc99ff Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 17:55:30 +0100 Subject: [PATCH 10/11] feat: allow multiple instances on same root --- src/ffi.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ffi.ts b/src/ffi.ts index 9f436d0..77c0ad8 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -40,8 +40,23 @@ if (Deno.build.os === 'windows') { const webview2loader = (await fetch(dataUrl)).body; //Overwrite local dll with the version specified in "url" - const fsFile = await Deno.open('./WebView2Loader.dll', { create: true, write: true }); - await webview2loader?.pipeTo(fsFile.writable); //fsFile is closed by the stream + try { + const fsFile = await Deno.open('./WebView2Loader.dll', { create: true, write: true }) + await webview2loader?.pipeTo(fsFile.writable); //fsFile is closed by the stream + } catch (e) { + const entries = await (async () => { + const array: Deno.DirEntry[] = [] + for await (const entry of Deno.readDir('.')) array.push(entry) + return array + })() + //Check if error is only caused by process lock + if (!entries.some(entry => entry.name === 'WebView2Loader.dll')) throw e + /** + * WebView2Loader.dll is already used + * Do not crash to allow multiple execution at the same root + * WebView2Loader.dll is correctly reùoved in unload() + */ + } self.addEventListener("unload", unload); } From a92b2dd190a8c4c22ca1b71c9e026448e408b5ab Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Tue, 29 Nov 2022 18:00:10 +0100 Subject: [PATCH 11/11] fmt: format edited code --- src/ffi.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ffi.ts b/src/ffi.ts index 77c0ad8..9c05664 100644 --- a/src/ffi.ts +++ b/src/ffi.ts @@ -33,7 +33,7 @@ export const instances: Webview[] = []; * * Does not need to be run on non-windows platforms, but that is subject to change. */ -if (Deno.build.os === 'windows') { +if (Deno.build.os === "windows") { //Download and cache `./WebView2Loader.dll` const { default: dll } = await import(`https://ejm.sh/${url}/WebView2Loader.dll?.json`, { assert: { type: 'json' } }) as { default: { b64: string } }; const dataUrl = `data:application/octet-stream;base64,${dll.b64}`; @@ -41,20 +41,20 @@ if (Deno.build.os === 'windows') { //Overwrite local dll with the version specified in "url" try { - const fsFile = await Deno.open('./WebView2Loader.dll', { create: true, write: true }) + const fsFile = await Deno.open("./WebView2Loader.dll", { create: true, write: true }); await webview2loader?.pipeTo(fsFile.writable); //fsFile is closed by the stream } catch (e) { const entries = await (async () => { - const array: Deno.DirEntry[] = [] - for await (const entry of Deno.readDir('.')) array.push(entry) - return array - })() + const array: Deno.DirEntry[] = []; + for await (const entry of Deno.readDir(".")) array.push(entry); + return array; + })(); //Check if error is only caused by process lock - if (!entries.some(entry => entry.name === 'WebView2Loader.dll')) throw e + if (!entries.some(entry => entry.name === "WebView2Loader.dll")) throw e; /** * WebView2Loader.dll is already used * Do not crash to allow multiple execution at the same root - * WebView2Loader.dll is correctly reùoved in unload() + * WebView2Loader.dll is correctly resolved in unload() */ }