Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: flutter/packages
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 565c65738619
Choose a base ref
...
head repository: flutter/packages
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 08faf6409187
Choose a head ref
  • 9 commits
  • 106 files changed
  • 6 contributors

Commits on Nov 9, 2026

  1. Configuration menu
    Copy the full SHA
    3d61a70 View commit details
    Browse the repository at this point in the history
  2. [ci] Remove pull_request_target workflows (#13581)

    Removes the remaining `pull_request_target` triggers in `.github/workflows/`:
    
    - Replaces `pull_request_label.yml` with `labeler-trigger.yml` (`pull_request`) and `labeler.yml` (`workflow_run`), matching flutter/flutter#195536.
    - Removes `remove_cicd.yml`, since `CICD` label management is now handled in Cocoon (matching flutter/flutter#189087).
    
    Part of flutter/flutter#193185
    
    ## Pre-Review Checklist
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.
    
    [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
    Piinks authored Nov 9, 2026
    Configuration menu
    Copy the full SHA
    9c7676b View commit details
    Browse the repository at this point in the history
  3. [vector_graphics_compiler] Resolve Flutter artifact cache via package…

    …:cli_util (#13252)
    
    Resolves the Flutter artifact cache directory (`<flutter>/bin/cache`) via `package:cli_util`'s `sdkPath` when `Platform.resolvedExecutable` is not `flutter_tester`.
    
    When `vector_graphics_compiler` is compiled to a standalone AOT executable (for example via `dart install vector_graphics_compiler` or `dart run vector_graphics_compiler@`), `Platform.resolvedExecutable` is the `vector_graphics_compiler` binary itself rather than `<flutter>/bin/cache/dart-sdk/bin/dart`, which previously prevented `initializePathOpsFromFlutterCache` and `initializeTessellatorFromFlutterCache` from finding the engine dynamic libraries.
    
    Part of dart-lang/sdk#63210
    
    ## Pre-Review Checklist
    
    [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
    sigurdm authored Nov 9, 2026
    Configuration menu
    Copy the full SHA
    bf4ce9e View commit details
    Browse the repository at this point in the history
  4. Sync release-material_ui-1.11.0 to main (#13605)

    This automated PR syncs the changes from the release branch release-material_ui-1.11.0 back to the main branch.
    fluttergithubbot authored Nov 9, 2026
    Configuration menu
    Copy the full SHA
    cd19277 View commit details
    Browse the repository at this point in the history
  5. Sync release-go_router-18.1.4 to main (#13606)

    This automated PR syncs the changes from the release branch release-go_router-18.1.4 back to the main branch.
    fluttergithubbot authored Nov 9, 2026
    Configuration menu
    Copy the full SHA
    c48fa01 View commit details
    Browse the repository at this point in the history
  6. [cross_file_web] Adds support to instantiate the web PlatformXFile wi…

    …thout needing to import web apis (#13395)
    
    Adds a `fromBytes` to `WebScopedStorageXFileCreationParams` so `XFile` can be instantiated without needing to import web APIs like `fromBlob`.
    
    Adds a `cross_file_web_safe.dart` library that imports `web_scoped_storage_cross_file_safe.dart` when not compiling on web.
    
    ## Pre-Review Checklist
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.
    
    [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
    bparrishMines authored Nov 9, 2026
    Configuration menu
    Copy the full SHA
    59b7e18 View commit details
    Browse the repository at this point in the history
  7. [pigeon] Fix standalone Native Interop @FlutterApi issues (#13609)

    Split out from #13576 per review. These are non-breaking fixes that can land on 29.x ahead of the 30.0.0 multi-engine changes.
    
    - [dart] Prefixes the internal `_<Api>Registrar` members (`dartApi`, `register`) with `pigeonVar_`. This means `@FlutterApi` methods named `register` or `dartApi` no longer collide with the JNIgen interface when `useJni` is enabled, so those names are no longer reserved.
    - [dart] `<FlutterApi>.implement` now defaults `name` to the default instance name and treats an empty `name` as the default. Previously it registered under `''`, which lookups never matched.
    - Pins `objective_c` to `<9.6.3` in the test packages and the native interop example app, to work around a debug-mode object validity check bug on the iOS simulator (dart-lang/native#3788).
    
    work towards flutter/flutter#195877
    
    ## Pre-Review Checklist
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.
    
    [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
    tarrinneal authored Nov 9, 2026
    Configuration menu
    Copy the full SHA
    13be8f6 View commit details
    Browse the repository at this point in the history

Commits on Nov 10, 2026

  1. [ci] Fix release workflows (#13611)

    #13581 broke release workflows
    
    Because labeler.yml runs on workflow_run: [requested, completed], whenever a normal PR triggers the requested event, its job-level if: evaluates to false and posts a triage check-run with conclusion: skipped onto main HEAD. Since the Wait on all tests step in release.yml sets allowed-conclusions: success,neutral, wait-on-check-action fails as soon as a triage: skipped check lands on that commit.
    
    ## Pre-Review Checklist
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.
    
    [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
    Piinks authored Nov 10, 2026
    Configuration menu
    Copy the full SHA
    3b97f56 View commit details
    Browse the repository at this point in the history
  2. [pigeon] Pass data classes and collections in a single buffer per nat…

    …ive interop call (#13265)
    
    Updates Kotlin JNI and Swift FFI native interop so that data classes, `List`, `Map`, and `Object` values are passed in a single buffer per call while keeping scalars, strings, enums, and typed data direct.
    
    ### Background & Motivation
    Previously, native interop converted every data class, `List`, `Map`, and `Object` into a graph of JVM or Objective-C objects, making a separate call across the language boundary for every field and collection element. For calls passing large or deeply nested data classes and collections, this per-element boundary overhead made native interop significantly slower than platform channels.
    
    ### Summary of Changes
    - **Single-Buffer Composite Value Transport**:
      - **Direct Types**: Scalars (`bool`, `int`, `double`), `String`, enums, and typed data (`Uint8List`, `Int32List`, `Int64List`, `Float64List`)—both non-nullable and nullable—continue to cross the JNI / FFI boundary directly as their own parameters and return values.
      - **Buffered Composite Types**: Data classes (including `sealed` class hierarchies), `List`, `Map`, and `Object`/`Any` arguments in a method call are encoded together into a single byte buffer using the generated `PigeonInteropCodec` (`StandardMessageCodec` format) and decoded in one pass on the receiving side. Composite return values and Kotlin `FlutterError.details` are similarly passed as a single encoded buffer.
      - **Unchanged User-Facing APIs**: The public Dart, Kotlin, and Swift APIs and registration methods (`HostApiRegistrar` / `HostApiSetup`, `FlutterApiRegistrar` / `FlutterApiProtocol`, data classes, and method signatures) are unchanged.
      - **Reduced Binding Surface**: Because composite types cross as `ByteArray` / `NSData` buffers, `jnigen` and `ffigen` only need to generate bindings for the `*Registrar`, `*Setup`, and `*Bridge` classes—not for every data class, sealed subclass, or enum.
    - **Additional Native Interop Optimizations**:
      - **Kotlin**: Replaces `entries.firstOrNull { it.raw == raw }` with constant-time `entries.getOrNull(raw)` in generated enum `ofRaw` lookups.
      - **Dart (JNI / FFI)**: Caches `JClass` lookups per class in lazy top-level variables (`_jniClass$<Name>`), converts JNI typed-data arrays directly via typed helpers, and copies FFI `NSData` to `Uint8List` once when deriving typed list views.
    - **Tests & Documentation**:
      - Updates the native interop integration test suite (`pigeons/native_interop_tests.dart`) and unit tests across the Dart, Kotlin, Swift, `jnigen`, and `ffigen` generators.
      - Updates `README.md` and `native_interop_guide.md`.
    
    # Pigeon Benchmark Comparison: Platform Channels vs. Native Interop (Objects) vs. Native Interop (Hybrid)
    
    This document compares the evolution of Pigeon's cross-language transport across three versions using measured release-mode benchmarks:
    
    &nbsp;
    
    1. **Platform Channel Pigeon** (`BasicMessageChannel` \+ `StandardMessageCodec`)  
    2. **Native Interop — Objects** (`NativeInteropTransport.objects` — JNI/FFI object-graph transport)  
    3. **Native Interop — Hybrid** (`NativeInteropTransport.hybrid` — direct interop for scalars/strings/enums/typed-data \+ single-buffer `StandardMessageCodec` for data classes and collections)
    
    &nbsp;
    
    ---
    
    ## 1\. Architectural Evolution Across the Three Versions
    
    | Dimension | 1\. Platform Channel Pigeon | 2\. Native Interop (`objects`) | 3\. Native Interop (`hybrid`) |
    | :---- | :---- | :---- | :---- |
    | **Call Dispatch** | Asynchronous (`BinaryMessenger` hop across platform thread) | Direct synchronous JNI (`package:jni`) / FFI (`dart:ffi`) | Direct synchronous JNI (`package:jni`) / FFI (`dart:ffi`) |
    | **Scalars, Strings, Enums** | Serialized into `ByteData` \+ async channel hop | **1 JNI/FFI call** per parameter | **1 JNI/FFI call** per parameter |
    | **Top-Level Typed Data (`Uint8List`, etc.)** | Copied through channel `ByteData` | **1 bulk buffer copy** (`getRange` / `memcpy`) | **1 bulk buffer copy** (`getRange` / `memcpy`) |
    | **Data Classes & Collections** | **1 buffer** (`StandardMessageCodec`) | **\$O(N \\cdot F)\$ JNI/FFI calls** (1 call per field, collection element, and wrapper allocation) | **1 JNI/FFI call** carrying a single `StandardMessageCodec` `Uint8List` buffer |
    | **Boundary Crossings for `List<AllNullableTypes>` (\$N=100\$)** | 1 async channel message | **\~7,500+ JNI/FFI calls** | **1 synchronous JNI/FFI call** |
    
    &nbsp;
    
    > \[\!IMPORTANT\] **Why `NativeInteropTransport.objects` regressed on complex types:** While `objects` mode eliminated the async platform-channel hop (making `noop` and scalar calls 35×–3,000× faster), it translated every class field and collection element into individual JNI/FFI calls (`JArrayList.add`, `JHashMap.put`, `JLong.valueOf`, and per-field getters/constructors). Under `hybrid` mode, Pigeon keeps the 1-call fast path for primitives, strings, enums, and `Uint8List`, while packing data classes and collections into a single contiguous `Uint8List` payload that crosses JNI/FFI in one bulk transfer.
    
    &nbsp;
    
    ---
    
    ## 2\. Release-Mode Per-Call Latency (`tool/benchmark.dart`)
    
    Measured via [`tool/benchmark.dart`](file:///Users/tarrinneal/work/packages/packages/pigeon/tool/benchmark.dart) running [`native_interop_benchmarks.dart`](file:///Users/tarrinneal/work/packages/packages/pigeon/platform_tests/shared_test_plugin_code/lib/native_interop_benchmarks.dart) in `--release` mode (up to 500 ms warmup and 201 timed samples per workload; `objects` mode includes the Phase 1 object-graph fixes such as cached `JClass`, bulk `JByteBuffer`, and pre-sized `JArrayList`).
    
    ### macOS Release (Swift FFI, Apple Silicon arm64)
    
    | Benchmark Workload | 1\. Platform Channel (p50) | 2\. Native Interop `objects` (p50 / p90) | 3\. Native Interop `hybrid` (p50 / p90) | `objects` vs. Channel | `hybrid` vs. `objects` | `hybrid` vs. Channel |
    | :---- | ----: | ----: | ----: | ----: | ----: | ----: |
    | `noop` | 11.63 µs | 0.20 µs / 0.23 µs | **0.20 µs** / 0.22 µs | 58.15× faster | 1.00× | **58.15× faster** |
    | `echoInt` | 14.00 µs | 0.39 µs / 0.44 µs | **0.39 µs** / 0.42 µs | 35.90× faster | 1.00× | **35.90× faster** |
    | `echoString` | 14.18 µs | 1.23 µs / 3.73 µs | **1.22 µs** / 3.64 µs | 11.53× faster | 1.01× | **11.62× faster** |
    | `echoUint8List 1MB` | 289.00 µs | 263.00 µs / 449.00 µs | **228.00 µs** / 442.00 µs | 1.10× faster | 1.15× faster | **1.27× faster** |
    | `echoAllTypes` (1 object) | 198.00 µs | 1.03 ms / 1.60 ms | **136.50 µs** / 142.50 µs | 🔴 5.20× slower | **7.55× faster** | **1.45× faster** |
    | `echoClassList` (`AllNullableTypes` ×1) | 254.00 µs | 1.35 ms / 1.93 ms | **162.00 µs** / 171.00 µs | 🔴 5.32× slower | **8.34× faster** | **1.57× faster** |
    | `echoClassList` (`AllNullableTypes` ×10) | 2.37 ms | 14.52 ms / 15.70 ms | **1.62 ms** / 1.69 ms | 🔴 6.13× slower | **8.96× faster** | **1.46× faster** |
    | `echoClassList` (`AllNullableTypes` ×100) | 23.94 ms | 149.62 ms / 155.24 ms | **16.36 ms** / 17.03 ms | 🔴 6.25× slower | **9.15× faster** | **1.46× faster** |
    | `echoClassList` (`AllNullableTypes` ×1000) | 246.17 ms | 1,482.94 ms / 1,554.68 ms | **170.37 ms** / 174.54 ms | 🔴 6.02× slower | **8.70× faster** | **1.44× faster** |
    | `echoIntList` (×10) | 21.13 µs | 17.42 µs / 18.33 µs | **2.10 µs** / 2.69 µs | 1.21× faster | **8.30× faster** | **10.06× faster** |
    | `echoIntList` (×100) | 62.00 µs | 138.00 µs / 145.00 µs | **9.26 µs** / 9.96 µs | 🔴 2.23× slower | **14.90× faster** | **6.70× faster** |
    | `echoIntList` (×1000) | 433.00 µs | 1.31 ms / 1.38 ms | **77.33 µs** / 83.33 µs | 🔴 3.02× slower | **16.91× faster** | **5.60× faster** |
    | `echoIntList` (×10000) | 4.10 ms | 18.79 ms / 19.48 ms | **756.00 µs** / 890.00 µs | 🔴 4.58× slower | **24.85× faster** | **5.42× faster** |
    | `echoIntMap` (×1000) | 891.00 µs | 8.87 ms / 14.44 ms | **178.00 µs** / 189.00 µs | 🔴 9.96× slower | **49.83× faster** | **5.01× faster** |
    | `callFlutterEchoClassList` (×100) | 49.50 ms | 1,620.53 ms / 1,818.44 ms | **33.00 ms** / 34.24 ms | 🔴 32.74× slower | **49.11× faster** | **1.50× faster** |
    
    ### Android Release (Kotlin JNI, `emulator-5554` arm64)
    
    | Benchmark Workload | 1\. Platform Channel (p50) | 2\. Native Interop `objects` (p50 / p90) | 3\. Native Interop `hybrid` (p50 / p90) | `objects` vs. Channel | `hybrid` vs. `objects` | `hybrid` vs. Channel |
    | :---- | ----: | ----: | ----: | ----: | ----: | ----: |
    | `noop` | 671.00 µs | 0.23 µs / 1.66 µs | **0.20 µs** / 0.67 µs | 2,917× faster | 1.15× faster | **3,355× faster** |
    | `echoInt` | 512.00 µs | 0.53 µs / 2.83 µs | **0.23 µs** / 0.51 µs | 966× faster | 2.30× faster | **2,226× faster** |
    | `echoString` | 362.00 µs | 6.33 µs / 33.95 µs | **6.38 µs** / 16.16 µs | 57.19× faster | 0.99× | **56.74× faster** |
    | `echoUint8List 1MB` | 8.22 ms | 2.77 ms / 9.23 ms | **3.48 ms** / 10.60 ms | 2.96× faster | 0.80× | **2.37× faster** |
    | `echoAllTypes` (1 object) | 1.06 ms | 2.61 ms / 4.75 ms | **370.00 µs** / 1.35 ms | 🔴 2.47× slower | **7.05× faster** | **2.86× faster** |
    | `echoClassList` (`AllNullableTypes` ×1) | 1.01 ms | 3.35 ms / 6.05 ms | **414.00 µs** / 3.15 ms | 🔴 3.30× slower | **8.09× faster** | **2.45× faster** |
    | `echoClassList` (`AllNullableTypes` ×10) | 5.92 ms | 42.78 ms / 68.42 ms | **3.01 ms** / 6.62 ms | 🔴 7.23× slower | **14.20× faster** | **1.96× faster** |
    | `echoClassList` (`AllNullableTypes` ×100) | 24.98 ms | 717.45 ms / 936.56 ms | **35.67 ms** / 58.50 ms | 🔴 28.72× slower | **20.11× faster** | **0.70×** (parity) |
    | `echoClassList` (`AllNullableTypes` ×1000) | 431.27 ms | 8,006.16 ms / 9,503.80 ms | **338.73 ms** / 421.96 ms | 🔴 18.56× slower | **23.64× faster** | **1.27× faster** |
    | `echoIntList` (×10) | 103.50 µs | 188.40 µs / 390.80 µs | **14.50 µs** / 17.00 µs | 🔴 1.82× slower | **12.99× faster** | **7.14× faster** |
    | `echoIntList` (×100) | 311.00 µs | 1.61 ms / 4.48 ms | **72.33 µs** / 129.33 µs | 🔴 5.18× slower | **22.26× faster** | **4.30× faster** |
    | `echoIntList` (×1000) | 1.06 ms | 24.75 ms / 41.37 ms | **705.00 µs** / 1.72 ms | 🔴 23.33× slower | **35.11× faster** | **1.50× faster** |
    | `echoIntList` (×10000) | 9.77 ms | 258.70 ms / 330.16 ms | **7.37 ms** / 14.15 ms | 🔴 26.48× slower | **35.12× faster** | **1.33× faster** |
    | `echoIntMap` (×1000) | 2.53 ms | 41.48 ms / 71.02 ms | **1.56 ms** / 2.88 ms | 🔴 16.40× slower | **26.63× faster** | **1.62× faster** |
    | `callFlutterEchoClassList` (×100) | 92.82 ms | 1,577.38 ms / 1,764.70 ms | **69.23 ms** / 106.86 ms | 🔴 16.99× slower | **22.78× faster** | **1.34× faster** |
    
    &nbsp;
    
    ---
    
    ## 3\. Pre-Optimization `objects` Baseline (`comparison_benchmarks.dart`)
    
    Before the Phase 1 object-graph fixes (when `objects` mode also performed uncached `JClass.forName` lookups on every call and element-by-element byte buffer copies), the original `comparison_benchmarks.dart` workloads measured in [baseline\_android\_release.log](file:///Users/tarrinneal/.gemini/jetski/brain/b230b33f-5257-469a-98b7-0ebfb02a2fca/scratch/baseline_android_release.log) and [baseline\_macos.log](file:///Users/tarrinneal/.gemini/jetski/brain/b230b33f-5257-469a-98b7-0ebfb02a2fca/scratch/baseline_macos.log) showed even larger gaps:
    
    &nbsp;
    
    | Legacy Workload (15-object list of `AllNullableTypes`) | 1\. Platform Channels | 2\. Original `objects` (Pre-Phase 1\) | 3\. Phase 1 `objects` | 4\. `hybrid` | Total Speedup (`hybrid` vs. Original `objects`) |
    | :---- | ----: | ----: | ----: | ----: | ----: |
    | **Android Host `echoClassList` (×15)** | 11.0 ms | 593.0 ms | 64.2 ms | **4.5 ms** | **131.8× faster** |
    | **Android Flutter `callFlutterEchoClassList` (×15)** | 11.0 ms | 1,485.0 ms | 236.6 ms | **10.4 ms** | **142.8× faster** |
    | **macOS Host `echoClassList` (×15)** | 16.0 ms | 176.0 ms | 21.8 ms | **2.4 ms** | **73.3× faster** |
    | **macOS Flutter `callFlutterEchoClassList` (×15)** | 53.0 ms | 294.0 ms | 243.1 ms | **4.9 ms** | **60.0× faster** |
    
    &nbsp;
    
    ---
    
    ## 4\. Summary of Key Takeaways
    
    1. **Platform Channels → Native Interop (`objects`):**  
       - Delivered **36×–3,355×** lower latency on `noop` and scalar calls by replacing asynchronous platform channel messages with synchronous JNI/FFI calls.  
       - However, even *with* Phase 1 optimizations (cached `JClass`, bulk `JByteBuffer`, pre-sized `JArrayList`), `objects` mode remained **5×–33× slower** than Platform Channels on complex data classes and collections (`1,482.94 ms` on macOS and `8,006.16 ms` on Android for 1,000 `AllNullableTypes` objects) because every field and collection element still crossed the JNI/FFI boundary individually.  
    2. **Native Interop (`objects`) → Native Interop (`hybrid`):**  
       - Preserves **100% of the scalar/primitive/string/typed-data speedups** of `objects` mode (`0.20 µs` `noop` on both macOS and Android).  
       - Speeds up data class and collection workloads by **7.5×–49.8×** over Phase 1 `objects` mode (and **60×–143×** over the original unoptimized `objects` mode) by serializing complex payloads into a single `StandardMessageCodec` byte buffer that crosses JNI/FFI in **1 call**.  
       - Outperforms **Platform Channels** across both simple and complex workloads:  
         - **36×–3,355× faster** on scalars and `noop`  
         - **11.6×–56.7× faster** on strings  
         - **1.33×–10.06× faster** on `List<int>` and `Map<int, int>` collections  
         - **1.27×–2.86× faster** on deeply nested `AllNullableTypes` data classes
    
    &nbsp;
    tarrinneal authored Nov 10, 2026
    Configuration menu
    Copy the full SHA
    08faf64 View commit details
    Browse the repository at this point in the history
Loading