Compare commits

...
7 Commits
Author SHA1 Message Date
Nico Burns 57d6794ad6 release v0.7.10 2026-07-30 15:33:31 -07:00
Nico Burns fda083bb65 Fix hotpatching when the bin target's crate name differs from the package name (#5719) (#5720)
(cherry picked from commit 4c51c12bc19d78983cb2992f319ebe996acb2893)

Signed-off-by: Nico Burns <nico@nicoburns.com>
2026-07-29 16:55:16 -07:00
Jonathan Kelley 3e43ffa6cf release v0.7.9 2026-05-07 17:09:43 -07:00
Jonathan Kelley bfcc111817 fix: git sha for cli 2026-05-07 16:59:46 -07:00
Jonathan Kelley d1ead872b1 fix: make instantiate async 2026-05-07 16:44:37 -07:00
Jonathan Kelley f5be0ea510 release v0.7.8 2026-05-07 15:28:20 -07:00
f1a0124227 backport iframe fix to v0.7 (#5535)
* feat:Add opt‑in navigation handler for external URLs (#5531)

* add navigation handler config option

code from https://github.com/DioxusLabs/dioxus/pull/5231

* Re-order branches

The branches should be reorder so that the branch that checks for
the index and assets is always taken first. Otherwise, they will
fail to load for users who forget to allow them in their custom
handlers, which will be a crappy experience and hard to debug.

* remove return

* Change behavior when handler not set

---------

Co-authored-by: not a cow <agielow@proton.me>

* fix: allow navigations but disallow external nav

---------

Co-authored-by: Martin Martinez Rivera <mrtnz.rvr@gmail.com>
Co-authored-by: not a cow <agielow@proton.me>
2026-05-07 15:11:47 -07:00
12 changed files with 340 additions and 168 deletions

No files matched your search

+12
View File
@@ -70,6 +70,18 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v5
with:
# Build from the tag we're releasing, not the branch the workflow
# was dispatched from. Without this the binary's Cargo.toml version
# and embedded SHA reflect whatever was on the dispatch branch.
ref: refs/tags/${{ github.event.inputs.post }}
- name: Resolve release commit SHA
shell: bash
run: |
sha=$(git rev-parse HEAD)
echo "DIOXUS_CLI_GIT_SHA=$sha" >> "$GITHUB_ENV"
echo "DIOXUS_CLI_GIT_SHA_SHORT=${sha:0:7}" >> "$GITHUB_ENV"
- name: Install openssl on macos - name: Install openssl on macos
if: matrix.platform.os == 'macos-latest' if: matrix.platform.os == 'macos-latest'
Generated
+56 -56
View File
@@ -3110,7 +3110,7 @@ dependencies = [
[[package]] [[package]]
name = "depinfo" name = "depinfo"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
] ]
@@ -3246,7 +3246,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus" name = "dioxus"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"criterion", "criterion",
"dioxus", "dioxus",
@@ -3288,7 +3288,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-asset-resolver" name = "dioxus-asset-resolver"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-cli-config", "dioxus-cli-config",
@@ -3309,7 +3309,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-autofmt" name = "dioxus-autofmt"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus-rsx", "dioxus-rsx",
"pretty_assertions", "pretty_assertions",
@@ -3323,7 +3323,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-cli" name = "dioxus-cli"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"ansi-to-html", "ansi-to-html",
"ansi-to-tui", "ansi-to-tui",
@@ -3451,7 +3451,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-cli-config" name = "dioxus-cli-config"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@@ -3467,7 +3467,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-cli-telemetry" name = "dioxus-cli-telemetry"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"chrono", "chrono",
"dirs", "dirs",
@@ -3479,7 +3479,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-component-manifest" name = "dioxus-component-manifest"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"schemars 1.2.1", "schemars 1.2.1",
"serde", "serde",
@@ -3488,7 +3488,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-config-macro" name = "dioxus-config-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -3496,11 +3496,11 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-config-macros" name = "dioxus-config-macros"
version = "0.7.7" version = "0.7.10"
[[package]] [[package]]
name = "dioxus-core" name = "dioxus-core"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"const_format", "const_format",
@@ -3531,7 +3531,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-core-macro" name = "dioxus-core-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"convert_case 0.8.0", "convert_case 0.8.0",
"dioxus", "dioxus",
@@ -3547,11 +3547,11 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-core-types" name = "dioxus-core-types"
version = "0.7.7" version = "0.7.10"
[[package]] [[package]]
name = "dioxus-desktop" name = "dioxus-desktop"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -3612,7 +3612,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-devtools" name = "dioxus-devtools"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus-cli-config", "dioxus-cli-config",
"dioxus-core", "dioxus-core",
@@ -3631,7 +3631,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-devtools-types" name = "dioxus-devtools-types"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus-core", "dioxus-core",
"serde", "serde",
@@ -3640,7 +3640,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-document" name = "dioxus-document"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-core", "dioxus-core",
@@ -3658,7 +3658,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-dx-wire-format" name = "dioxus-dx-wire-format"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"cargo_metadata", "cargo_metadata",
"manganis-core", "manganis-core",
@@ -3707,7 +3707,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-ext" name = "dioxus-ext"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus-autofmt", "dioxus-autofmt",
"dioxus-rsx-rosetta", "dioxus-rsx-rosetta",
@@ -3718,7 +3718,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-fullstack" name = "dioxus-fullstack"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-stream", "async-stream",
@@ -3785,7 +3785,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-fullstack-core" name = "dioxus-fullstack-core"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum-core 0.5.6", "axum-core 0.5.6",
@@ -3813,7 +3813,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-fullstack-macro" name = "dioxus-fullstack-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"axum 0.8.9", "axum 0.8.9",
"const_format", "const_format",
@@ -3829,7 +3829,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-history" name = "dioxus-history"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-core", "dioxus-core",
@@ -3838,7 +3838,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-hooks" name = "dioxus-hooks"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-core", "dioxus-core",
@@ -3856,7 +3856,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-html" name = "dioxus-html"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"bytes", "bytes",
@@ -3887,7 +3887,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-html-internal-macro" name = "dioxus-html-internal-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"convert_case 0.8.0", "convert_case 0.8.0",
"proc-macro2", "proc-macro2",
@@ -3898,7 +3898,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-interpreter-js" name = "dioxus-interpreter-js"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus-core", "dioxus-core",
"dioxus-core-types", "dioxus-core-types",
@@ -3916,7 +3916,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-liveview" name = "dioxus-liveview"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"axum 0.8.9", "axum 0.8.9",
"dioxus", "dioxus",
@@ -3944,7 +3944,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-logger" name = "dioxus-logger"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-cli-config", "dioxus-cli-config",
@@ -3955,7 +3955,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-native" name = "dioxus-native"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyrender", "anyrender",
"anyrender_vello", "anyrender_vello",
@@ -3990,7 +3990,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-native-dom" name = "dioxus-native-dom"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"blitz-dom", "blitz-dom",
"blitz-traits", "blitz-traits",
@@ -4115,7 +4115,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-router" name = "dioxus-router"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"axum 0.8.9", "axum 0.8.9",
"base64 0.22.1", "base64 0.22.1",
@@ -4143,7 +4143,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-router-macro" name = "dioxus-router-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"base16", "base16",
"digest", "digest",
@@ -4157,7 +4157,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-rsx" name = "dioxus-rsx"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"prettier-please", "prettier-please",
"prettyplease", "prettyplease",
@@ -4170,7 +4170,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-rsx-hotreload" name = "dioxus-rsx-hotreload"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus-core", "dioxus-core",
"dioxus-core-types", "dioxus-core-types",
@@ -4185,7 +4185,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-rsx-rosetta" name = "dioxus-rsx-rosetta"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"convert_case 0.8.0", "convert_case 0.8.0",
"dioxus-autofmt", "dioxus-autofmt",
@@ -4201,7 +4201,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-server" name = "dioxus-server"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -4263,7 +4263,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-signals" name = "dioxus-signals"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-core", "dioxus-core",
@@ -4283,7 +4283,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-ssr" name = "dioxus-ssr"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"askama_escape", "askama_escape",
"dioxus", "dioxus",
@@ -4294,7 +4294,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-stores" name = "dioxus-stores"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
"dioxus-core", "dioxus-core",
@@ -4305,7 +4305,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-stores-macro" name = "dioxus-stores-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"convert_case 0.8.0", "convert_case 0.8.0",
"dioxus", "dioxus",
@@ -4325,7 +4325,7 @@ dependencies = [
[[package]] [[package]]
name = "dioxus-web" name = "dioxus-web"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"ciborium", "ciborium",
"dioxus", "dioxus",
@@ -5468,7 +5468,7 @@ dependencies = [
[[package]] [[package]]
name = "generational-box" name = "generational-box"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"criterion", "criterion",
"parking_lot", "parking_lot",
@@ -7885,7 +7885,7 @@ dependencies = [
[[package]] [[package]]
name = "lazy-js-bundle" name = "lazy-js-bundle"
version = "0.7.7" version = "0.7.10"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
@@ -8303,7 +8303,7 @@ dependencies = [
[[package]] [[package]]
name = "manganis" name = "manganis"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"const-serialize 0.7.2", "const-serialize 0.7.2",
"const-serialize 0.8.0-alpha.0", "const-serialize 0.8.0-alpha.0",
@@ -8317,7 +8317,7 @@ dependencies = [
[[package]] [[package]]
name = "manganis-core" name = "manganis-core"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"const-serialize 0.7.2", "const-serialize 0.7.2",
"const-serialize 0.8.0-alpha.0", "const-serialize 0.8.0-alpha.0",
@@ -8338,7 +8338,7 @@ dependencies = [
[[package]] [[package]]
name = "manganis-macro" name = "manganis-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dunce", "dunce",
"macro-string", "macro-string",
@@ -12547,7 +12547,7 @@ dependencies = [
[[package]] [[package]]
name = "ssr-only" name = "ssr-only"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
] ]
@@ -12815,7 +12815,7 @@ dependencies = [
[[package]] [[package]]
name = "subsecond" name = "subsecond"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"libc", "libc",
@@ -12841,7 +12841,7 @@ dependencies = [
[[package]] [[package]]
name = "subsecond-types" name = "subsecond-types"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@@ -12873,7 +12873,7 @@ dependencies = [
[[package]] [[package]]
name = "suspense-carousel" name = "suspense-carousel"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"async-std", "async-std",
"dioxus", "dioxus",
@@ -14521,7 +14521,7 @@ dependencies = [
[[package]] [[package]]
name = "wasm-split-cli" name = "wasm-split-cli"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -14554,7 +14554,7 @@ dependencies = [
[[package]] [[package]]
name = "wasm-split-macro" name = "wasm-split-macro"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"base16", "base16",
"digest", "digest",
@@ -14566,7 +14566,7 @@ dependencies = [
[[package]] [[package]]
name = "wasm-splitter" name = "wasm-splitter"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"async-once-cell", "async-once-cell",
"wasm-split-macro", "wasm-split-macro",
@@ -14587,7 +14587,7 @@ dependencies = [
[[package]] [[package]]
name = "wasm-used" name = "wasm-used"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"id-arena", "id-arena",
"tracing", "tracing",
@@ -15351,7 +15351,7 @@ dependencies = [
[[package]] [[package]]
name = "windows-headless" name = "windows-headless"
version = "0.7.7" version = "0.7.10"
dependencies = [ dependencies = [
"dioxus", "dioxus",
] ]
+52 -52
View File
@@ -114,71 +114,71 @@ members = [
[workspace.package] [workspace.package]
version = "0.7.7" version = "0.7.10"
# dependencies that are shared across packages # dependencies that are shared across packages
[workspace.dependencies] [workspace.dependencies]
dioxus = { path = "packages/dioxus", version = "0.7.7" } dioxus = { path = "packages/dioxus", version = "0.7.10" }
dioxus-core = { path = "packages/core", version = "0.7.7" } dioxus-core = { path = "packages/core", version = "0.7.10" }
dioxus-core-types = { path = "packages/core-types", version = "0.7.7" } dioxus-core-types = { path = "packages/core-types", version = "0.7.10" }
dioxus-core-macro = { path = "packages/core-macro", version = "0.7.7" } dioxus-core-macro = { path = "packages/core-macro", version = "0.7.10" }
dioxus-config-macro = { path = "packages/config-macro", version = "0.7.7" } dioxus-config-macro = { path = "packages/config-macro", version = "0.7.10" }
dioxus-router = { path = "packages/router", version = "0.7.7" } dioxus-router = { path = "packages/router", version = "0.7.10" }
dioxus-router-macro = { path = "packages/router-macro", version = "0.7.7" } dioxus-router-macro = { path = "packages/router-macro", version = "0.7.10" }
dioxus-document = { path = "packages/document", version = "0.7.7", default-features = false } dioxus-document = { path = "packages/document", version = "0.7.10", default-features = false }
dioxus-history = { path = "packages/history", version = "0.7.7", default-features = false } dioxus-history = { path = "packages/history", version = "0.7.10", default-features = false }
dioxus-html = { path = "packages/html", version = "0.7.7", default-features = false } dioxus-html = { path = "packages/html", version = "0.7.10", default-features = false }
dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.7.7" } dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.7.10" }
dioxus-hooks = { path = "packages/hooks", version = "0.7.7" } dioxus-hooks = { path = "packages/hooks", version = "0.7.10" }
dioxus-web = { path = "packages/web", version = "0.7.7", default-features = false } dioxus-web = { path = "packages/web", version = "0.7.10", default-features = false }
dioxus-ssr = { path = "packages/ssr", version = "0.7.7", default-features = false } dioxus-ssr = { path = "packages/ssr", version = "0.7.10", default-features = false }
dioxus-desktop = { path = "packages/desktop", version = "0.7.7", default-features = false } dioxus-desktop = { path = "packages/desktop", version = "0.7.10", default-features = false }
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.7.7" } dioxus-interpreter-js = { path = "packages/interpreter", version = "0.7.10" }
dioxus-liveview = { path = "packages/liveview", version = "0.7.7" } dioxus-liveview = { path = "packages/liveview", version = "0.7.10" }
dioxus-autofmt = { path = "packages/autofmt", version = "0.7.7" } dioxus-autofmt = { path = "packages/autofmt", version = "0.7.10" }
dioxus-rsx = { path = "packages/rsx", version = "0.7.7" } dioxus-rsx = { path = "packages/rsx", version = "0.7.10" }
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.7.7" } dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.7.10" }
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.7.7" } dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.7.10" }
dioxus-signals = { path = "packages/signals", version = "0.7.7" } dioxus-signals = { path = "packages/signals", version = "0.7.10" }
dioxus-stores = { path = "packages/stores", version = "0.7.7" } dioxus-stores = { path = "packages/stores", version = "0.7.10" }
dioxus-stores-macro = { path = "packages/stores-macro", version = "0.7.7" } dioxus-stores-macro = { path = "packages/stores-macro", version = "0.7.10" }
dioxus-devtools = { path = "packages/devtools", version = "0.7.7" } dioxus-devtools = { path = "packages/devtools", version = "0.7.10" }
dioxus-devtools-types = { path = "packages/devtools-types", version = "0.7.7" } dioxus-devtools-types = { path = "packages/devtools-types", version = "0.7.10" }
dioxus-fullstack = { path = "packages/fullstack", version = "0.7.7", default-features = false } dioxus-fullstack = { path = "packages/fullstack", version = "0.7.10", default-features = false }
dioxus-fullstack-core = { path = "packages/fullstack-core", version = "0.7.7", default-features = false } dioxus-fullstack-core = { path = "packages/fullstack-core", version = "0.7.10", default-features = false }
dioxus-fullstack-macro = { path = "packages/fullstack-macro", version = "0.7.7", default-features = false } dioxus-fullstack-macro = { path = "packages/fullstack-macro", version = "0.7.10", default-features = false }
dioxus-server = { path = "packages/fullstack-server", version = "0.7.7" } dioxus-server = { path = "packages/fullstack-server", version = "0.7.10" }
dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.7.7" } dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.7.10" }
dioxus-logger = { path = "packages/logger", version = "0.7.7" } dioxus-logger = { path = "packages/logger", version = "0.7.10" }
dioxus-native = { path = "packages/native", version = "0.7.7" } dioxus-native = { path = "packages/native", version = "0.7.10" }
dioxus-native-dom = { path = "packages/native-dom", version = "0.7.7" } dioxus-native-dom = { path = "packages/native-dom", version = "0.7.10" }
dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.7.7" } dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.7.10" }
dioxus-config-macros = { path = "packages/config-macros", version = "0.7.7" } dioxus-config-macros = { path = "packages/config-macros", version = "0.7.10" }
dioxus-component-manifest = { path = "packages/component-manifest", version = "0.7.7" } dioxus-component-manifest = { path = "packages/component-manifest", version = "0.7.10" }
generational-box = { path = "packages/generational-box", version = "0.7.7" } generational-box = { path = "packages/generational-box", version = "0.7.10" }
lazy-js-bundle = { path = "packages/lazy-js-bundle", version = "0.7.7" } lazy-js-bundle = { path = "packages/lazy-js-bundle", version = "0.7.10" }
# cli # cli
dioxus-cli-telemetry = { path = "packages/cli-telemetry", version = "0.7.7" } dioxus-cli-telemetry = { path = "packages/cli-telemetry", version = "0.7.10" }
dioxus-cli-config = { path = "packages/cli-config", version = "0.7.7" } dioxus-cli-config = { path = "packages/cli-config", version = "0.7.10" }
# subsecond # subsecond
subsecond-types = { path = "packages/subsecond/subsecond-types", version = "0.7.7" } subsecond-types = { path = "packages/subsecond/subsecond-types", version = "0.7.10" }
subsecond = { path = "packages/subsecond/subsecond", version = "0.7.7" } subsecond = { path = "packages/subsecond/subsecond", version = "0.7.10" }
# wasm-split # wasm-split
wasm-splitter = { path = "packages/wasm-split/wasm-split", version = "0.7.7" } wasm-splitter = { path = "packages/wasm-split/wasm-split", version = "0.7.10" }
wasm-split-macro = { path = "packages/wasm-split/wasm-split-macro", version = "0.7.7" } wasm-split-macro = { path = "packages/wasm-split/wasm-split-macro", version = "0.7.10" }
wasm-split-cli = { path = "packages/wasm-split/wasm-split-cli", version = "0.7.7" } wasm-split-cli = { path = "packages/wasm-split/wasm-split-cli", version = "0.7.10" }
wasm-used = { path = "packages/wasm-split/wasm-used", version = "0.7.7" } wasm-used = { path = "packages/wasm-split/wasm-used", version = "0.7.10" }
# our dep-info parsing crate # our dep-info parsing crate
depinfo = { path = "packages/depinfo", version = "0.7.7" } depinfo = { path = "packages/depinfo", version = "0.7.10" }
# manganis # manganis
manganis = { path = "packages/manganis/manganis", version = "0.7.7" } manganis = { path = "packages/manganis/manganis", version = "0.7.10" }
manganis-core = { path = "packages/manganis/manganis-core", version = "0.7.7" } manganis-core = { path = "packages/manganis/manganis-core", version = "0.7.10" }
manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.7.7" } manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.7.10" }
manganis-core-07 = { path = "packages/manganis/manganis-07", version = "0.7.2" } manganis-core-07 = { path = "packages/manganis/manganis-07", version = "0.7.2" }
# const-serialize. # const-serialize.
+11 -4
View File
@@ -98,12 +98,19 @@
); );
in in
{ {
packages.dioxus-cli = ( packages.dioxus-cli =
rustPackage "dioxus-cli" { (rustPackage "dioxus-cli" {
binary = "dx"; binary = "dx";
features = [ "no-downloads" ]; features = [ "no-downloads" ];
} }).overrideAttrs
); (_: {
# The nix sandbox has no .git and no .cargo_vcs_info.json, so
# build.rs has nothing to derive the commit from. Pass the
# flake's own input rev through the env-var override path.
# `self.rev` is set on a clean tree; `dirtyRev` on a dirty one
# (and includes a `-dirty` suffix, which build.rs accepts).
DIOXUS_CLI_GIT_SHA = inputs.self.rev or inputs.self.dirtyRev or "";
});
packages.default = self'.packages.dioxus-cli; packages.default = self'.packages.dioxus-cli;
checks.dioxus-cli = self'.packages.dioxus-cli; checks.dioxus-cli = self'.packages.dioxus-cli;
+128 -21
View File
@@ -1,38 +1,145 @@
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
fn main() { fn main() {
println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA"); println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA");
println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA_SHORT"); println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA_SHORT");
println!("cargo:rerun-if-changed=.git/HEAD");
println!("cargo:rerun-if-changed=.git/refs");
let full_hash = std::env::var("DIOXUS_CLI_GIT_SHA").ok().or_else(|| { let manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let output = Command::new("git") let git_dir = find_git_dir(&manifest_dir);
.args(["rev-parse", "HEAD"])
.output()
.ok()?;
if !output.status.success() { // Track the files that determine the current commit. Absolute paths are
return None; // required because the build script runs from `packages/cli/`, not the
// workspace root where `.git` lives.
if let Some(git_dir) = git_dir.as_deref() {
emit_rerun(&git_dir.join("HEAD"));
emit_rerun(&git_dir.join("packed-refs"));
if let Some(target) = head_ref_target(git_dir) {
emit_rerun(&git_dir.join(target));
} }
}
emit_rerun(&manifest_dir.join(".cargo_vcs_info.json"));
let hash = String::from_utf8(output.stdout).ok()?; let full_hash = env_nonempty("DIOXUS_CLI_GIT_SHA")
let hash = hash.trim().to_string(); .or_else(|| git_dir.as_deref().and_then(read_head_sha))
.or_else(|| read_cargo_vcs_info(&manifest_dir))
if hash.is_empty() { .or_else(|| git_cli_sha(&manifest_dir));
None
} else {
Some(hash)
}
});
if let Some(full_hash) = full_hash { if let Some(full_hash) = full_hash {
let full_hash = full_hash.trim();
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA={full_hash}"); println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA={full_hash}");
let short_hash = std::env::var("DIOXUS_CLI_GIT_SHA_SHORT") let short_hash = env_nonempty("DIOXUS_CLI_GIT_SHA_SHORT")
.ok()
.unwrap_or_else(|| full_hash.chars().take(7).collect()); .unwrap_or_else(|| full_hash.chars().take(7).collect());
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA_SHORT={short_hash}"); println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA_SHORT={short_hash}");
} }
} }
fn env_nonempty(key: &str) -> Option<String> {
env::var(key).ok().filter(|s| !s.trim().is_empty())
}
fn emit_rerun(path: &Path) {
println!("cargo:rerun-if-changed={}", path.display());
}
/// Walk up from `start` looking for `.git`. Handles the file form used by
/// git worktrees and submodules, where `.git` contains `gitdir: <path>`.
fn find_git_dir(start: &Path) -> Option<PathBuf> {
for dir in start.ancestors() {
let candidate = dir.join(".git");
let meta = match fs::metadata(&candidate) {
Ok(m) => m,
Err(_) => continue,
};
if meta.is_dir() {
return Some(candidate);
}
if meta.is_file() {
let contents = fs::read_to_string(&candidate).ok()?;
let pointer = contents
.lines()
.find_map(|l| l.strip_prefix("gitdir:"))?
.trim();
let resolved = if Path::new(pointer).is_absolute() {
PathBuf::from(pointer)
} else {
dir.join(pointer)
};
return Some(resolved);
}
}
None
}
/// If HEAD is a symbolic ref (`ref: refs/heads/foo`), return the target path.
fn head_ref_target(git_dir: &Path) -> Option<String> {
let head = fs::read_to_string(git_dir.join("HEAD")).ok()?;
head.strip_prefix("ref:").map(|s| s.trim().to_owned())
}
fn read_head_sha(git_dir: &Path) -> Option<String> {
let head = fs::read_to_string(git_dir.join("HEAD")).ok()?;
let head = head.trim();
let Some(target) = head.strip_prefix("ref:").map(str::trim) else {
// Detached HEAD: the file holds the SHA directly.
return is_sha(head).then(|| head.to_owned());
};
// Loose ref file.
if let Ok(sha) = fs::read_to_string(git_dir.join(target)) {
let sha = sha.trim();
if is_sha(sha) {
return Some(sha.to_owned());
}
}
// Packed refs (after `git gc` / shallow clones, refs only live here).
let packed = fs::read_to_string(git_dir.join("packed-refs")).ok()?;
for line in packed.lines() {
if line.starts_with('#') || line.starts_with('^') || line.is_empty() {
continue;
}
let (sha, name) = line.split_once(' ')?;
if name == target && is_sha(sha) {
return Some(sha.to_owned());
}
}
None
}
/// Cargo writes `.cargo_vcs_info.json` next to `Cargo.toml` when publishing,
/// recording the source SHA at publish time. This is how `cargo install`
/// from crates.io can still report a real commit despite the `.crate`
/// tarball having no `.git/`.
fn read_cargo_vcs_info(manifest_dir: &Path) -> Option<String> {
let contents = fs::read_to_string(manifest_dir.join(".cargo_vcs_info.json")).ok()?;
// Cheap targeted parse so we don't pull serde into the build script.
// The file is generated by cargo and the field name is stable.
let after = contents.split("\"sha1\"").nth(1)?;
let sha = after.split('"').nth(1)?.trim();
is_sha(sha).then(|| sha.to_owned())
}
fn git_cli_sha(manifest_dir: &Path) -> Option<String> {
// Scope `git` to the manifest dir so we never accidentally pick up a
// SHA from a parent repo (e.g. someone's `~` is a git repo).
let output = Command::new("git")
.arg("-C")
.arg(manifest_dir)
.args(["rev-parse", "HEAD"])
.output()
.ok()?;
if !output.status.success() {
return None;
}
let sha = String::from_utf8(output.stdout).ok()?.trim().to_owned();
is_sha(&sha).then_some(sha)
}
fn is_sha(s: &str) -> bool {
matches!(s.len(), 40 | 64) && s.chars().all(|c| c.is_ascii_hexdigit())
}
+3 -1
View File
@@ -408,7 +408,9 @@ impl AppBuilder {
// patch (starting from changed_crates + cascade). That serves a different purpose — it only // patch (starting from changed_crates + cascade). That serves a different purpose — it only
// compiles what changed now, not everything ever modified. Both use workspace_dependents_of // compiles what changed now, not everything ever modified. Both use workspace_dependents_of
// for the BFS, so they stay in sync automatically. // for the BFS, so they stay in sync automatically.
let tip_crate_name = self.build.main_target.replace('-', "_"); // Track the tip by *package* name — that's the identity used by the file→crate
// mapping and the workspace dependents graph (the bin target name can differ).
let tip_crate_name = self.build.tip_package_name();
self.modified_crates.insert(tip_crate_name.clone()); self.modified_crates.insert(tip_crate_name.clone());
// Add changed crates and their transitive workspace dependents (cascade). // Add changed crates and their transitive workspace dependents (cascade).
+3 -1
View File
@@ -614,7 +614,9 @@ impl BuildRequest {
modified_crates: &HashSet<String>, modified_crates: &HashSet<String>,
) -> Result<Vec<String>> { ) -> Result<Vec<String>> {
// Exclude the tip crate — it's compiled separately via cargo_build after replay. // Exclude the tip crate — it's compiled separately via cargo_build after replay.
let tip = self.tip_crate_name(); // Modified crates are tracked by *package* name, which can differ from the bin
// target name (`tip_crate_name()`), e.g. package `browser` with `[[bin]] name = "blitz"`.
let tip = self.tip_package_name();
let crates: HashSet<&String> = modified_crates let crates: HashSet<&String> = modified_crates
.iter() .iter()
.filter(|name| **name != tip) .filter(|name| **name != tip)
+11 -1
View File
@@ -2581,6 +2581,16 @@ impl BuildRequest {
self.main_target.replace('-', "_") self.main_target.replace('-', "_")
} }
/// The workspace package name of the tip crate (hyphens replaced with underscores).
///
/// This can differ from `tip_crate_name()` when the binary target is named differently
/// than its package (e.g. package `browser` with `[[bin]] name = "blitz"`). Use this for
/// workspace-graph lookups (which are keyed by package name) and `tip_crate_name()` for
/// rustc `--crate-name` keys like `{name}.bin`.
pub(crate) fn tip_package_name(&self) -> String {
self.package().name.replace('-', "_")
}
/// Stderr captured from the linker during the last build. Written by the linker /// Stderr captured from the linker during the last build. Written by the linker
/// interception in `rustcwrapper` and read back to surface warnings/errors to the user. /// interception in `rustcwrapper` and read back to surface warnings/errors to the user.
fn link_err_file(&self) -> PathBuf { fn link_err_file(&self) -> PathBuf {
@@ -3095,7 +3105,7 @@ impl BuildRequest {
}) })
.collect(); .collect();
let tip = self.tip_crate_name(); let tip = self.tip_package_name();
let Some(tip_nid) = krates.workspace_members().find_map(|m| match m { let Some(tip_nid) = krates.workspace_members().find_map(|m| match m {
krates::Node::Krate { id, krate, .. } if krate.name.replace('-', "_") == tip => { krates::Node::Krate { id, krate, .. } if krate.name.replace('-', "_") == tip => {
krates.nid_for_kid(id) krates.nid_for_kid(id)
+1 -1
View File
@@ -1187,7 +1187,7 @@ impl AppServer {
/// Uses BFS from the tip crate through its workspace dependencies to find the path. /// Uses BFS from the tip crate through its workspace dependencies to find the path.
/// If the changed crate IS the tip crate, returns just `[tip]`. /// If the changed crate IS the tip crate, returns just `[tip]`.
pub(crate) fn workspace_dep_chain(&self, changed_crate: &str) -> Vec<String> { pub(crate) fn workspace_dep_chain(&self, changed_crate: &str) -> Vec<String> {
let tip_name = self.client.build.main_target.replace('-', "_"); let tip_name = self.client.build.tip_package_name();
// If the changed crate is the tip, no chain needed // If the changed crate is the tip, no chain needed
if changed_crate == tip_name { if changed_crate == tip_name {
+13
View File
@@ -20,6 +20,10 @@ type CustomEventHandler = Box<
), ),
>; >;
/// A function taking a URL and returning whether the webview should navigate to it or open it in
/// the browser. If missing in the config, all URLs will be allowed.
type NavigationHandler = Box<dyn Fn(&str) -> bool + 'static>;
/// The closing behaviour of specific application window. /// The closing behaviour of specific application window.
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive] #[non_exhaustive]
@@ -70,6 +74,7 @@ pub struct Config {
pub(crate) disable_dma_buf_on_wayland: bool, pub(crate) disable_dma_buf_on_wayland: bool,
pub(crate) additional_windows_args: Option<String>, pub(crate) additional_windows_args: Option<String>,
pub(crate) tray_icon_show_window_on_click: bool, pub(crate) tray_icon_show_window_on_click: bool,
pub(crate) navigation_handler: Option<NavigationHandler>,
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>, pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>,
@@ -124,6 +129,7 @@ impl Config {
on_window: None, on_window: None,
additional_windows_args: None, additional_windows_args: None,
tray_icon_show_window_on_click: true, tray_icon_show_window_on_click: true,
navigation_handler: None,
} }
} }
@@ -350,6 +356,13 @@ impl Config {
self.tray_icon_show_window_on_click = show; self.tray_icon_show_window_on_click = show;
self self
} }
/// Set a custom navigation handler for non-dioxus URLs.
/// Return true to allow navigation inside the webview, false to block.
pub fn with_navigation_handler(mut self, f: impl Fn(&str) -> bool + 'static) -> Self {
self.navigation_handler = Some(Box::new(f));
self
}
} }
impl Default for Config { impl Default for Config {
+17 -12
View File
@@ -353,6 +353,7 @@ impl WebviewInstance {
} }
}; };
let navigation_handler = cfg.navigation_handler.take();
let page_loaded = AtomicBool::new(false); let page_loaded = AtomicBool::new(false);
let mut webview = WebViewBuilder::new_with_web_context(&mut web_context) let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
@@ -367,25 +368,29 @@ impl WebviewInstance {
.with_url("dioxus://index.html/") .with_url("dioxus://index.html/")
.with_ipc_handler(ipc_handler) .with_ipc_handler(ipc_handler)
.with_navigation_handler(move |var| { .with_navigation_handler(move |var| {
// We don't want to allow any navigation // Serve the index and assets.
// We only want to serve the index file and assets
if var.starts_with("dioxus://") if var.starts_with("dioxus://")
|| var.starts_with("http://dioxus.") || var.starts_with("http://dioxus.")
|| var.starts_with("https://dioxus.") || var.starts_with("https://dioxus.")
{ {
// After the page has loaded once, don't allow any more navigation // After the page has loaded once, don't allow any more navigation
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst); let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
!page_loaded return !page_loaded;
} else {
if var.starts_with("http://")
|| var.starts_with("https://")
|| var.starts_with("mailto:")
{
_ = webbrowser::open(&var);
}
false
} }
}) // prevent all navigations
// External links always open somewhere else. Prevents the webview from navigating
if var.starts_with("http://")
|| var.starts_with("https://")
|| var.starts_with("mailto:")
{
_ = webbrowser::open(&var);
return false;
}
// By default, external links are allowed. This keeps things like iframes working.
// However, users can customize this to allow/disallow domains/routes/patterns.
navigation_handler.as_ref().map(|f| f(&var)).unwrap_or(true)
})
.with_asynchronous_custom_protocol(String::from("dioxus"), request_handler); .with_asynchronous_custom_protocol(String::from("dioxus"), request_handler);
// Enable https scheme on android, needed for secure context API, like the geolocation API // Enable https scheme on android, needed for secure context API, like the geolocation API
+33 -19
View File
@@ -594,24 +594,31 @@ pub unsafe fn apply_patch(mut table: JumpTable) -> Result<(), PatchError> {
.unwrap() .unwrap()
.unchecked_into(); .unchecked_into();
// ── SYNC SECTION — no `.await` past this point ──────────────── // ── HOST-STATE-MUTATING SECTION ───────────────────────────────
// //
// Everything below mutates shared JS state (linear memory, the // Below we grow shared linear memory and the indirect function
// indirect function table, the patch's data segment) and the // table, then async-instantiate the patch into them and commit
// jump-table pointer. We must not yield, because: // the new jump table. There IS one `.await` for the instantiate
// (we can't avoid it: Chrome disallows synchronous
// `new WebAssembly.Instance` on the main thread for modules
// larger than 8MB, and patches routinely cross that), but it's
// safe — the original race we fixed wasn't about yielding here:
// //
// * `memory.grow` detaches the previous `ArrayBuffer`. The old // * `memory.grow` and `funcs.grow` each return their PRIOR
// code captured `memory.buffer()` BEFORE the awaits and then // length atomically. Concurrent `apply_patch` tasks therefore
// read its `byteLength` to compute `__memory_base`; if any // each get a unique, non-overlapping `memory_base` /
// other task ran a `memory.grow` during the awaits (e.g. an // `table_base`, so two patches can't land on the same region.
// allocator call from a concurrent render), the snapshot was // * Host code can't observe the half-instantiated patch: the
// detached, `byteLength` returned 0, and the patch's data // new memory pages are zero, the new table slots are null,
// segment ended up loaded over the host's stack/rodata. // and the jump table isn't committed until the very end of
// * Two concurrent `apply_patch` tasks must not interleave // this block, so nothing redirects through the new slots.
// between memory/table grow and `commit_patch`. Doing all // * The original bug — using `memory.buffer().byteLength()`
// side-effecting work in one synchronous turn guarantees that. // captured before the awaits, which returned 0 if the buffer
// * If the future is cancelled before this point, host state // had been detached by a concurrent grow — is gone because
// is untouched. // we derive `memory_base` from `memory.grow()`'s return
// value instead.
// * Cancellation between grow and `commit_patch` leaks memory
// pages and table slots, but doesn't corrupt anything.
const PAGE_SIZE: u32 = 64 * 1024; const PAGE_SIZE: u32 = 64 * 1024;
let patch_pages = (dl_bytes.byte_length() as f64 / PAGE_SIZE as f64).ceil() as u32 + 1; let patch_pages = (dl_bytes.byte_length() as f64 / PAGE_SIZE as f64).ceil() as u32 + 1;
@@ -646,9 +653,16 @@ pub unsafe fn apply_patch(mut table: JumpTable) -> Result<(), PatchError> {
let imports = Object::new(); let imports = Object::new();
Reflect::set(&imports, &"env".into(), &env).unwrap(); Reflect::set(&imports, &"env".into(), &env).unwrap();
// Synchronous instantiation of the precompiled module — writes // Async instantiation of the precompiled module. We use the
// the patch's data segment into memory at `memory_base`. // (Module, imports) form of `WebAssembly.instantiate`, which
let instance = Instance::new(&module, &imports).unwrap(); // resolves directly to an `Instance` (not `{module, instance}`).
// This is the no-size-limit path; the synchronous
// `new WebAssembly.Instance` constructor is capped at 8MB on
// Chrome's main thread.
let instance: Instance = JsFuture::from(WebAssembly::instantiate_module(&module, &imports))
.await
.unwrap()
.unchecked_into();
let inst_exports: Object = instance.exports(); let inst_exports: Object = instance.exports();
// Run the patch's relocation thunks and constructors. Order // Run the patch's relocation thunks and constructors. Order