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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changes/explicit-resource-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@tauri-apps/api": minor:enhance
---

Add ECMAScript Explicit Resource Management to Resource. You can now use the `using` syntax in supported browsers or with polyfills:

```javascript
import { create, BaseDirectory } from "@tauri-apps/plugin-fs"
...
{
await using file = await create("foo/bar.txt", { baseDir: BaseDirectory.AppConfig });
await file.write(new TextEncoder().encode("Hello world"));
// Before `file` goes out of scope, it is disposed by calling `file[Symbol.asyncDispose]()` and awaited.
}
```
12 changes: 12 additions & 0 deletions .changes/lock-minor-versions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"tauri": minor:changes
"tauri-runtime": minor:changes
"tauri-runtime-wry": minor:changes
"tauri-build": minor:changes
"tauri-macros": minor:changes
"tauri-codegen": minor:changes
"tauri-cli": minor:changes
"@tauri-apps/cli": minor:changes
---

Lock unstable tauri crates to minor versions.
14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ rust-version = "1.90"

[workspace.dependencies]
tauri = { version = "2.11.5", path = "./crates/tauri", default-features = false }
tauri-runtime = { version = "2.11.3", path = "./crates/tauri-runtime" }
tauri-runtime-wry = { version = "2.11.4", path = "./crates/tauri-runtime-wry", default-features = false }
tauri-runtime = { version = "~2.11.3", path = "./crates/tauri-runtime" }
tauri-runtime-wry = { version = "~2.11.4", path = "./crates/tauri-runtime-wry", default-features = false }
tauri-build = { version = "2.6.3", path = "./crates/tauri-build", default-features = false }
tauri-macros = { version = "2.6.3", path = "./crates/tauri-macros" }
tauri-codegen = { version = "2.6.3", path = "./crates/tauri-codegen" }
tauri-utils = { version = "2.9.3", path = "./crates/tauri-utils" }
tauri-macros = { version = "~2.6.3", path = "./crates/tauri-macros" }
tauri-codegen = { version = "~2.6.3", path = "./crates/tauri-codegen" }
tauri-utils = { version = "~2.9.3", path = "./crates/tauri-utils" }
tauri-plugin = { version = "2.6.3", path = "./crates/tauri-plugin", default-features = false }
tauri-bundler = { version = "2.9.4", path = "./crates/tauri-bundler", default-features = false }
tauri-macos-sign = { version = "2.3.4", path = "./crates/tauri-macos-sign" }
tauri-bundler = { version = "=2.9.4", path = "./crates/tauri-bundler", default-features = false }
tauri-macos-sign = { version = "=2.3.4", path = "./crates/tauri-macos-sign" }

# default to small, optimized workspace release binaries
[profile.release]
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri/scripts/bundle.global.js

Large diffs are not rendered by default.

79 changes: 64 additions & 15 deletions packages/api/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,29 +257,43 @@ async function invoke<T>(
}

/**
* Convert a device file path to an URL that can be loaded by the webview.
* Note that `asset:` and `http://asset.localhost` must be added to [`app.security.csp`](https://v2.tauri.app/reference/config/#csp-1) in `tauri.conf.json`.
* Example CSP value: `"csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost"` to use the asset protocol on image sources.
* Convert a device file path to a URL that can be loaded by the webview.
*
* Additionally, `"enable" : "true"` must be added to [`app.security.assetProtocol`](https://v2.tauri.app/reference/config/#assetprotocolconfig)
* in `tauri.conf.json` and its access scope must be defined on the `scope` array on the same `assetProtocol` object.
* The asset protocol must be enabled and the files you want to expose must be
* included in its scope. The protocol origins must also be allowed by the
* relevant [`app.security.csp`](https://v2.tauri.app/reference/config/#csp-1)
* directive. For example, this configuration allows images from the user's
* downloads directory:
*
* ```json
* {
* "app": {
* "security": {
* "assetProtocol": {
* "enable": true,
* "scope": ["$DOWNLOAD/**"]
* },
* "csp": "default-src 'self'; img-src 'self' asset: http://asset.localhost"
* }
* }
* }
* ```
*
* See [`assetProtocol`](https://v2.tauri.app/reference/config/#assetprotocolconfig)
* for the available scope variables and platform-specific protocol details.
*
* @param filePath The file path.
* @param protocol The protocol to use. Defaults to `asset`. You only need to set this when using a custom protocol.
* @example
* ```typescript
* import { appDataDir, join } from '@tauri-apps/api/path';
* import { downloadDir, join } from '@tauri-apps/api/path';
* import { convertFileSrc } from '@tauri-apps/api/core';
* const appDataDirPath = await appDataDir();
* const filePath = await join(appDataDirPath, 'assets/video.mp4');
* const downloads = await downloadDir();
* const filePath = await join(downloads, 'photo.png');
* const assetUrl = convertFileSrc(filePath);
*
* const video = document.getElementById('my-video');
* const source = document.createElement('source');
* source.type = 'video/mp4';
* source.src = assetUrl;
* video.appendChild(source);
* video.load();
* const image = document.getElementById('my-image') as HTMLImageElement;
* image.src = assetUrl;
* ```
*
* @return the URL that can be used as source on the webview.
Expand All @@ -295,11 +309,14 @@ function convertFileSrc(filePath: string, protocol = 'asset'): string {
*
* The resource lives in the main process and does not exist
* in the Javascript world, and thus will not be cleaned up automatically
* except on application exit. If you want to clean it up early, call {@linkcode Resource.close}
* except on application exit. If you want to clean it up early, call {@linkcode Resource.close} or use [Explicit Resource Management].
*
* To support older browsers with [Explicit Resource Management], use a supported compiler (e.g. tsc) or bundler (e.g. rollup).
*
* @example
* ```typescript
* import { Resource, invoke } from '@tauri-apps/api/core';
*
* export class DatabaseHandle extends Resource {
* static async open(path: string): Promise<DatabaseHandle> {
* const rid: number = await invoke('open_db', { path });
Expand All @@ -311,6 +328,34 @@ function convertFileSrc(filePath: string, protocol = 'asset'): string {
* }
* }
* ```
*
* To use with [Explicit Resource Management]:
*
* @example
* ```
* await using db = await DatabaseHandle.open('test.db');
* await db.execute('SELECT *');
* ```
*
* To support older browsers, add the following to the globals (e.g. adding to the HTML file):
*
* ```javascript
* Symbol.dispose ??= Symbol("Symbol.dispose");
* Symbol.asyncDispose ??= Symbol("Symbol.asyncDispose");
* ```
*
* And for the compiler, for example `tsc`, `rollup`, `vite`, add the following to `tsconfig.json`:
*
* ```json
* {
* "compilerOptions": {
* "target": "es2022",
* "lib": ["es2022", "esnext.disposable", "dom"]
* }
* }
* ```
*
* [Explicit Resource Management]: https://github.com/tc39/proposal-explicit-resource-management
*/
export class Resource {
readonly #rid: number
Expand All @@ -332,6 +377,10 @@ export class Resource {
rid: this.rid
})
}

async [Symbol.asyncDispose]() {
await this.close()
}
}

function isTauri(): boolean {
Expand Down
3 changes: 2 additions & 1 deletion packages/api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"strict": true,
"noUnusedLocals": true,
"noImplicitAny": true,
"noEmit": true
"noEmit": true,
"lib": ["es2022", "esnext.disposable", "dom"]
}
}
Loading