From 9a2ccbaf5ed6a1050fa697af23b03dac9534acbf Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 25 Jul 2026 15:07:44 -0700 Subject: [PATCH 1/4] Bump Flutter version in .fvmrc to 3.44.8 Updates the FVM-pinned Flutter SDK from 3.44.7 to 3.44.8 so local and CI environments use the newer patch release consistently. --- .fvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.fvmrc b/.fvmrc index 405fa8ce4b..e4be7182f3 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.44.7" + "flutter": "3.44.8" } From d78e54061b126562f7ee3225031547bb60cf4bab Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 25 Jul 2026 17:18:35 -0700 Subject: [PATCH 2/4] Pin serious_python 4.4.0 and python-build 20260725 Fixes iOS apps built with 'flet build ipa' crashing at startup with 'Failed to lookup symbol serious_python_run: dlsym(RTLD_DEFAULT, serious_python_run): symbol not found'. serious_python shipped dart_bridge -- the in-process Dart<->Python transport -- as a static library linked into the app executable. An iOS executable exports nothing to the dynamic symbol table by default and the release build strips local symbols, so the dlsym lookups Dart (DynamicLibrary.process()) and Python ('import dart_bridge') perform at runtime could not resolve. Only release/archive device builds under the Swift Package Manager path were affected: debug/simulator don't dead-strip, and Android was never affected (its dart_bridge is a dynamic .so that exports its symbols). serious_python 4.4.0 ships dart_bridge as a dynamic framework, embedded and signed into the app like Python.xcframework with its symbols exported. Its bundled python-build snapshot moves to 20260725 (dart_bridge 1.5.1 -> 1.6.1, Pyodide 3.14 314.0.2 -> 314.0.3), so PYTHON_BUILD_RELEASE_DATE is re-pinned to match -- the two must reference the same python-build release. Bundled Python versions (3.12.13 / 3.13.14 / 3.14.6) are unchanged. Verified the pinned manifest resolves: 3.12.13 / 3.13.14 / 3.14.6 with Pyodide 314.0.3 on 3.14. --- CHANGELOG.md | 2 ++ .../packages/flet-cli/src/flet_cli/utils/python_versions.py | 2 +- .../templates/build/{{cookiecutter.out_dir}}/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b798b6710..bd767c8c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ### Bug fixes +* Fix iOS apps built with `flet build ipa` crashing at startup with `Failed to lookup symbol 'serious_python_run': dlsym(RTLD_DEFAULT, serious_python_run): symbol not found`. `serious_python` shipped `dart_bridge` — which provides the in-process Dart↔Python transport — as a **static** library linked into the app executable. An iOS executable exports nothing to the dynamic symbol table by default and the release build strips local symbols, so the `dlsym` lookups that Dart (`DynamicLibrary.process()`) and Python (`import dart_bridge`) perform at runtime could not resolve. Only release/archive (device) builds under the Swift Package Manager path were affected — debug and simulator builds don't dead-strip, so the failure did not reproduce there, and Android was never affected (its `dart_bridge` is a dynamic `.so`, which exports its symbols). Bumps `serious_python` to **4.4.0**, which ships `dart_bridge` as a dynamic framework — embedded and signed into the app like `Python.xcframework`, with its symbols exported — and re-pins the bundled python-build snapshot to **20260725** (`dart_bridge` **1.5.1 → 1.6.1**, Pyodide 3.14 **314.0.2 → 314.0.3**); the bundled Python versions (**3.12.13 / 3.13.14 / 3.14.6**) are unchanged by @FeodorFitsner. + * Fix `MatplotlibChart` freezing permanently when its platform view is disposed with a frame in flight — the common trigger is switching to another tab inside the app, which races the frame stream: `DataChannel.send` on a disposed channel silently drops, so the frame's `[0xFF]` frame-applied ack never arrives and `_send_and_wait`'s unbounded await parks `MatplotlibChart._receive_loop` — the sole consumer of the frame queue — for the rest of the session, with no exception raised; remounting opens a fresh channel but the stale ack futures were never resolved, so the chart stayed frozen. `_capture_channel` now resolves all pending ack futures when a new channel is captured (a fresh channel means every pending ack belongs to the disposed one), unparking the producer instantly on remount, and the ack await is bounded by `FRAME_ACK_TIMEOUT` (5s; a healthy ack lands in milliseconds) — on expiry the frame is dropped and its future removed from the ack FIFO so subsequent acks keep resolving the right entries ([#6709](https://github.com/flet-dev/flet/issues/6709), [#6710](https://github.com/flet-dev/flet/pull/6710)) by @ForsakenDurian. * Fix a system/edge-swipe back gesture exiting the whole host app instead of navigating back when it lands on an embedded `FletApp` (an app rendered inside another Flet app — e.g. a gallery host running example apps in-process). The embedded app's `WidgetsApp` (`MaterialApp`/`CupertinoApp`) ran the default `NavigationNotification` handler, which reported `SystemNavigator.setFrameworkHandlesBack(false)` for a nested app that couldn't pop (typically a single-view example) and swallowed the notification, so the OS finished the whole activity on back and the host never got to report that it could pop. An embedded page now lets that notification bubble to the host (which re-reports `canHandlePop`) and chains a `ChildBackButtonDispatcher` to the host Router, so a system back propagates to the host and pops the view that embeds it by @FeodorFitsner. * Fix `page.window.maximized = True` intermittently reverting to unmaximized right after startup on macOS, when set in the same patch as `page.title` (e.g. `page.title = "My App"; page.window.maximized = True` in `main()`) by @davidlawson. diff --git a/sdk/python/packages/flet-cli/src/flet_cli/utils/python_versions.py b/sdk/python/packages/flet-cli/src/flet_cli/utils/python_versions.py index 832f2b47bc..7e2d88131e 100644 --- a/sdk/python/packages/flet-cli/src/flet_cli/utils/python_versions.py +++ b/sdk/python/packages/flet-cli/src/flet_cli/utils/python_versions.py @@ -28,7 +28,7 @@ # python-build release this flet pins. Keep in sync with serious_python's # `pythonReleaseDate` (lib/src/python_versions.dart) — both should track the # same python-build release. -PYTHON_BUILD_RELEASE_DATE = "20260720" +PYTHON_BUILD_RELEASE_DATE = "20260725" RELEASE_DATE_ENV = "FLET_PYTHON_BUILD_RELEASE_DATE" MANIFEST_PATH_ENV = "FLET_PYTHON_BUILD_MANIFEST" diff --git a/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml b/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml index ae15ce7cbc..ed71be3afe 100644 --- a/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml +++ b/sdk/python/templates/build/{{cookiecutter.out_dir}}/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: flet: path: ../../../../../packages/flet - serious_python: 4.3.6 + serious_python: 4.4.0 # MsgPack codec used by the dart_bridge FletBackendChannel implementation # in lib/main.dart — matches the wire format flet's existing socket From 042dca5ab28750a0c3f6e79391cbf3b6a4cdcda1 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 25 Jul 2026 19:07:09 -0700 Subject: [PATCH 3/4] Run embedded FletApps over the in-process dart_bridge transport An embedded FletApp (a Flet program hosted inside another Flet app -- a gallery, a preview) could only reach its host over a socket. On mobile that means a Unix domain socket, whose path is capped at ~104 bytes: on the iOS simulator the container path overflows it and every embedded app fails with "AF_UNIX path too long". It is also needlessly slow for two programs sharing one process. Embedded apps can now use dart_bridge, the same in-process transport the root app already uses. dart_bridge channels are keyed by a Dart-allocated native port, so the rendezvous is inverted compared to the socket flow: - FletAppControl sees url="dartbridge://", asks the registered connector for a channel, and hands the allocated port to the host's Python via a new FletApp "connect" control event. - The host serves that port with a FletDartBridgeServer. The channel's existing send-retry loop covers the window before the handler registers. The flet package stays free of any serious_python dependency: it exposes a process-global embeddedDartBridgeConnector hook that the build template's native_runtime.dart registers, reusing the PythonBridge-backed channel and data-channel factory already defined there. Each embedded app mints its own PythonBridge, and high-throughput DataChannels (RawImage, MatplotlibChart) get dedicated bridges as before. Opt-in and backwards compatible: without the scheme, or where dart_bridge does not exist (web, desktop dev), FletApp keeps using the URL-scheme channel factory, so hosts can fall back to a socket URL. --- CHANGELOG.md | 2 ++ packages/flet/lib/flet.dart | 1 + .../lib/src/controls/flet_app_control.dart | 30 ++++++++++++++++ .../flet/lib/src/embedded_dart_bridge.dart | 36 +++++++++++++++++++ .../flet/src/flet/controls/core/flet_app.py | 11 ++++++ .../lib/native_runtime.dart | 21 +++++++++++ 6 files changed, 101 insertions(+) create mode 100644 packages/flet/lib/src/embedded_dart_bridge.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index bd767c8c9e..063abf6864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Improvements +* An embedded `FletApp` can now run over the in-process `dart_bridge` transport instead of a socket. Set `url="dartbridge://"` and the client allocates a native channel, delivers its port through the new `FletApp.on_connect` event, and the host serves that port with a `FletDartBridgeServer` — so a Flet program hosted inside another Flet app (a gallery, a preview) exchanges messages at memcpy speed with no socket file, no TCP port, and no `AF_UNIX` path-length limit (which broke embedded apps on the iOS simulator, where the container path overflows `sun_path`). High-throughput `DataChannel`s used by embedded apps (`RawImage`, `MatplotlibChart`) get their own dedicated bridge too. The transport is opt-in and falls back to the existing URL-scheme channels: on web and desktop dev builds, where `dart_bridge` is unavailable, hosts keep using a socket URL by @FeodorFitsner. + * `flet run` can now pass custom arguments to your app script: everything after a `--` separator is forwarded to the script instead of being parsed by Flet, and arrives there as `sys.argv[1:]` - e.g. `flet run --web main.py -- --dataset big.csv --verbose`. Previously there was no way to do this: the app was always launched as `python -u