diff --git a/.changes/updater-js-options-not-mutated.md b/.changes/updater-js-options-not-mutated.md new file mode 100644 index 000000000..ecfe93576 --- /dev/null +++ b/.changes/updater-js-options-not-mutated.md @@ -0,0 +1,6 @@ +--- +updater: patch +updater-js: patch +--- + +`check()`, `Update.download()` and `Update.downloadAndInstall()` no longer replace the `headers` of the options object they are given with an array. diff --git a/packages/api-e2e/test/specs/updater.spec.ts b/packages/api-e2e/test/specs/updater.spec.ts index 5d35684a1..c25ff15e6 100644 --- a/packages/api-e2e/test/specs/updater.spec.ts +++ b/packages/api-e2e/test/specs/updater.spec.ts @@ -74,4 +74,14 @@ describePlugin('updater', { desktopOnly: true }, () => { }) expect(version).toBe(UPDATER_FIXTURE_VERSION) }) + + it('check does not modify the options it is given', async () => { + const headers = await tauri(async (api) => { + const options = { headers: { 'x-e2e-updater': 'yes' } } + const update = await api.updater.check(options) + await update?.close() + return options.headers + }) + expect(headers).toEqual({ 'x-e2e-updater': 'yes' }) + }) }) diff --git a/plugins/updater/api-iife.js b/plugins/updater/api-iife.js index 520d07189..c7f1c7f64 100644 --- a/plugins/updater/api-iife.js +++ b/plugins/updater/api-iife.js @@ -1 +1 @@ -if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e,n){"use strict";class t extends n.Resource{constructor(e){super(e.rid),this.available=!0,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body,this.rawJson=e.rawJson}async download(e,t){a(t);const s=new n.Channel;e&&(s.onmessage=e);const d=await n.invoke("plugin:updater|download",{onEvent:s,rid:this.rid,...t});await(this.downloadedBytes?.close().catch(()=>{})),this.downloadedBytes=new n.Resource(d)}async install(e){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await n.invoke("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid,...e}),this.downloadedBytes=void 0}async downloadAndInstall(e,t){a(t);const s=new n.Channel;e&&(s.onmessage=e),await n.invoke("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...t})}async close(){await(this.downloadedBytes?.close()),await super.close()}}function a(e){e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries()))}return e.Update=t,e.check=async function(e){a(e);const s=await n.invoke("plugin:updater|check",{...e});return s?new t(s):null},e}({},window.__TAURI__.core);Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})} +if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e,n){"use strict";class a extends n.Resource{constructor(e){super(e.rid),this.available=!0,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body,this.rawJson=e.rawJson}async download(e,a){const s=new n.Channel;e&&(s.onmessage=e);const d=await n.invoke("plugin:updater|download",{onEvent:s,rid:this.rid,...a,headers:t(a?.headers)});await(this.downloadedBytes?.close().catch(()=>{})),this.downloadedBytes=new n.Resource(d)}async install(e){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await n.invoke("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid,...e}),this.downloadedBytes=void 0}async downloadAndInstall(e,a){const s=new n.Channel;e&&(s.onmessage=e),await n.invoke("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...a,headers:t(a?.headers)})}async close(){await(this.downloadedBytes?.close()),await super.close()}}function t(e){return e?Array.from(new Headers(e).entries()):void 0}return e.Update=a,e.check=async function(e){const s=await n.invoke("plugin:updater|check",{...e,headers:t(e?.headers)});return s?new a(s):null},e}({},window.__TAURI__.core);Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})} diff --git a/plugins/updater/guest-js/index.ts b/plugins/updater/guest-js/index.ts index f2b2dd519..e33ef0b8e 100644 --- a/plugins/updater/guest-js/index.ts +++ b/plugins/updater/guest-js/index.ts @@ -155,7 +155,6 @@ class Update extends Resource { onEvent?: (progress: DownloadEvent) => void, options?: DownloadOptions ): Promise { - convertToRustHeaders(options) const channel = new Channel() if (onEvent) { channel.onmessage = onEvent @@ -163,7 +162,8 @@ class Update extends Resource { const downloadedBytesRid = await invoke('plugin:updater|download', { onEvent: channel, rid: this.rid, - ...options + ...options, + headers: toRustHeaders(options?.headers) }) // release the bytes of a previous download, which would otherwise be kept // in memory until the webview is destroyed @@ -234,7 +234,6 @@ class Update extends Resource { onEvent?: (progress: DownloadEvent) => void, options?: DownloadOptions & InstallOptions ): Promise { - convertToRustHeaders(options) const channel = new Channel() if (onEvent) { channel.onmessage = onEvent @@ -242,7 +241,8 @@ class Update extends Resource { await invoke('plugin:updater|download_and_install', { onEvent: channel, rid: this.rid, - ...options + ...options, + headers: toRustHeaders(options?.headers) }) } @@ -286,21 +286,21 @@ class Update extends Resource { * @since 2.0.0 */ async function check(options?: CheckOptions): Promise { - convertToRustHeaders(options) - const metadata = await invoke('plugin:updater|check', { - ...options + ...options, + headers: toRustHeaders(options?.headers) }) return metadata ? new Update(metadata) : null } /** - * Converts the headers in options to be an {@linkcode Array<[string, string]>} which is what the Rust side expects + * Converts headers to an {@linkcode Array<[string, string]>}, which is what the Rust side expects, + * without modifying the caller's options. */ -function convertToRustHeaders(options?: { headers?: HeadersInit }) { - if (options?.headers) { - options.headers = Array.from(new Headers(options.headers).entries()) - } +function toRustHeaders( + headers?: HeadersInit +): Array<[string, string]> | undefined { + return headers ? Array.from(new Headers(headers).entries()) : undefined } export type { CheckOptions, DownloadOptions, DownloadEvent }