)]}'
{
  "commit": "d822fe82e9a62ca357500a2a1e7805c81a4f2b58",
  "tree": "637b4ca47449e491c9bd651a565febd8cddf9b59",
  "parents": [
    "84c0da3dda865e69c26047608e0d0195e8d3ac4f"
  ],
  "author": {
    "name": "LongCatIsLooong",
    "email": "31859944+LongCatIsLooong@users.noreply.github.com",
    "time": "Tue May 19 16:02:08 2026 -0700"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Tue May 19 23:02:08 2026 +0000"
  },
  "message": "Enable Swift testing in the iOS embedder (#185712)\n\nThis patch:\n1. Updates the `-mios-simulator-version-min` ldflag to `15.0` (this\nfixes the crash during test discovery).\n2. refactors swiftc.py a bit, moves the target triplet logic from\ndarwin/BUILD.gn to swiftc.py so you can override the ios version in a\ntest target (but it\u0027s not absolutely necessary for this change since\nit\u0027s the linker flag that makes the difference).\n3. Migrates a few xctest tests to swift testing tests. The names of the\ntests are kept as-is so the diff is easier to read.\n\n\n### The Crash \n```\n(lldb) bt\n* thread #9, name \u003d \u0027[Swift Testing] test discovery - loading test #0 (Task 3)\u0027, queue \u003d \u0027com.apple.root.user-initiated-qos.cooperative\u0027, stop reason \u003d EXC_BAD_ACCESS (code\u003d1, address\u003d0x0)\n  * frame #0: 0x0000000000000000 \n    frame #1: 0x000000010ad0fb80 libios_test_flutter.dylib`closure #1() in variable initialization expression of static AccessibilityFeaturesTests.$s22ios_test_flutter_swift26AccessibilityFeaturesTestsV43accessibilityFeatureFlagRawValuesAreCorrect4TestfMp_24accessorc8120add5c86a9e3fMu_ at @__swiftmacro_22ios_test_flutter_swift26AccessibilityFeaturesTestsV43accessibilityFeatureFlagRawValuesAreCorrect4TestfMp_.swift:0\n    frame #2: 0x000000010224a39c Testing`partial apply for closure #1 in __checkClosureCall(performing:throws:mismatchExplanation:expression:comments:isRequired:sourceLocation:)\n    frame #3: 0x000000010224a39c Testing`partial apply for closure #1 in __checkClosureCall(performing:throws:mismatchExplanation:expression:comments:isRequired:sourceLocation:)\n    frame #4: 0x00000001022d8de8 Testing`(1) await resume partial function for generic specialization \u003c(Testing.Test, Testing.Runner.Plan.Action)\u003e of reabstraction thunk helper \u003cτ_0_0 where τ_0_0: Swift.Sendable\u003e from @escaping @isolated(any) @callee_guaranteed @async () -\u003e (@out τ_0_0) to @escaping @callee_guaranteed @async () -\u003e (@out τ_0_0, @error @owned Swift.Error)\n    frame #5: 0x000000010224ae24 Testing`closure #1 in __checkClosureCall(throws:performing:expression:comments:isRequired:sourceLocation:)\n```\n\nInitially I thought swift testing doesn\u0027t support test discovery in\nlinked dylibs but it\u0027s apparently not the case. And according to gemini\nit\u0027s not anything else in a binary but\n```\nLoad command 9\n        cmd LC_BUILD_VERSION\n   platform 7\n-     minos 14.0\n+     minos 15.6\n        sdk 26.4\n```\n\nAs it tried to use `15.6` in `swift_flags` and put `14.0` in `ldflags`\nand hit the same crash.\n\nThis is what gemini has to say:\n\u003e This is the definitive end of the road! 🔬\n\u003e \n\u003e I have mathematically eliminated every other variable in computing\nexistence. Between a binary that crashes and a binary that runs,\nliterally NOTHING changed except that single number.\n\n\nAlso it thinks it\u0027s because of this in `dyld`:\n\u003e Look at the code in dyldMain.cpp at Line 430:\n\u003e \n\u003e cpp\n\u003e // dyldMain.cpp Line 430\n\u003e // TODO: Remove once drop support for simulators older than iOS 17,\ntvOS 15, and watchOS 8\n\u003e mach_o::PlatformAndVersions pvs \u003d dyldSimHdr-\u003eplatformAndVersions();\n\u003e mach_o::Policy policy(mach_o::Architecture(), pvs, 0);\n\u003e // [!!] THE SMOKING GUN [!!]\n\u003e // Old simulators add the main executable to all_image_info in the\nsimulator process, not in the host\n\u003e if ( policy.enforceImageListRemoveMainExecutable() ) {\n\u003e     STACK_ALLOC_ARRAY(const mach_header*, mhs, 1);\n\u003e     mhs.push_back(state.config.process.mainExecutableMF);\n\u003e     std::span\u003cconst mach_header*\u003e mhSpan(\u0026mhs[0], 1);\n\u003e     \n\u003e     // LITERALLY REMOVES THE IMAGE FROM THE TRACKING TABLE!!\n\u003e state.externallyViewable-\u003eremoveImages(state.persistentAllocator,\nephemeralAllocator, mhSpan);\n\u003e }\n\u003e Why this triggers your exact crash:\n\u003e The Condition: policy.enforceImageListRemoveMainExecutable()\nexplicitly returns true for all binaries linked below a specific epoch\n(iOS 15/16).\n\u003e The Destructive Action: Because dyld thinks it needs to work around an\nancient Simulator bug, it explicitly calls removeImages, ripping your\nbinary\u0027s tracking data directly out of the global tracking table\n(all_image_info).\n\u003e The Crash: Modern Swift Testing and the Swift Runtime rely on scanning\nall_image_info to discover where the @Test sections are in memory!\n\u003e The Final Blow: Because dyld just destructively hid the image from the\ntracking table, the Swift Runtime couldn\u0027t look it up, failed to resolve\nthe internal metadata pointers, and instantly crashed in\nswift_getTypeByMangledName.\n\u003e By simply lying and writing minos 15.0 into the header, you caused\npolicy.enforceImageListRemoveMainExecutable() to return false, totally\ndisabling this destructive legacy workaround and leaving your image\nintact for Swift to find! 🔬🏆🏁\n\n## Pre-launch Checklist\n\n- [ ] I read the [Contributor Guide] and followed the process outlined\nthere for submitting PRs.\n- [ ] I read the [AI contribution guidelines] and understand my\nresponsibilities, or I am not using AI tools.\n- [ ] I read the [Tree Hygiene] wiki page, which explains my\nresponsibilities.\n- [ ] I read and followed the [Flutter Style Guide], including [Features\nwe expect every widget to implement].\n- [ ] I signed the [CLA].\n- [ ] I listed at least one issue that this PR fixes in the description\nabove.\n- [ ] I updated/added relevant documentation (doc comments with `///`).\n- [ ] I added new tests to check the change I am making, or this PR is\n[test-exempt].\n- [ ] I followed the [breaking change policy] and added [Data Driven\nFixes] where supported.\n- [ ] All existing and new tests are passing.\n\nIf you need help, consider asking for advice on the #hackers-new channel\non [Discord].\n\nIf this change needs to override an active code freeze, provide a\ncomment explaining why. The code freeze workflow can be overridden by\ncode reviewers. See pinned issues for any active code freezes with\nguidance.\n\n**Note**: The Flutter team is currently trialing the use of [Gemini Code\nAssist for\nGitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).\nComments from the `gemini-code-assist` bot should not be taken as\nauthoritative feedback from the Flutter team. If you find its comments\nuseful you can update your code accordingly, but if you are unsure or\ndisagree with the feedback, please feel free to wait for a Flutter team\nmember\u0027s review for guidance on which automated comments should be\naddressed.\n\n\u003c!-- Links --\u003e\n[Contributor Guide]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview\n[AI contribution guidelines]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines\n[Tree Hygiene]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md\n[test-exempt]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests\n[Flutter Style Guide]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md\n[Features we expect every widget to implement]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement\n[CLA]: https://cla.developers.google.com/\n[flutter/tests]: https://github.com/flutter/tests\n[breaking change policy]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes\n[Discord]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md\n[Data Driven Fixes]:\nhttps://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "61c58c70c57f8be22b5d9f9fc6bd46c01d60a406",
      "old_mode": 33188,
      "old_path": "engine/src/build/config/darwin/BUILD.gn",
      "new_id": "9973145780f97cc7ea1dbc71121774e24be52f99",
      "new_mode": 33188,
      "new_path": "engine/src/build/config/darwin/BUILD.gn"
    },
    {
      "type": "modify",
      "old_id": "6c3cd0ce907ab07b78d2720c1e1db229d2824874",
      "old_mode": 33188,
      "old_path": "engine/src/build/config/darwin/darwin_sdk.gni",
      "new_id": "0907a72684e39fbcab373ff4fb4cf33ca66f20d6",
      "new_mode": 33188,
      "new_path": "engine/src/build/config/darwin/darwin_sdk.gni"
    },
    {
      "type": "modify",
      "old_id": "d4769d2ee2e6544537dd90fec8e4c576d1cd9b2d",
      "old_mode": 33261,
      "old_path": "engine/src/build/toolchain/darwin/swiftc.py",
      "new_id": "bd37c5a67159183713d3d43d48bb7acff084610d",
      "new_mode": 33261,
      "new_path": "engine/src/build/toolchain/darwin/swiftc.py"
    },
    {
      "type": "modify",
      "old_id": "62c95db6581e00231f4732b1c019fb6dd2d8f806",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/darwin/common/BUILD.gn",
      "new_id": "b0202de010016f3dbfe57226bc0e16f93ff22911",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/darwin/common/BUILD.gn"
    },
    {
      "type": "modify",
      "old_id": "16d5db73fd8a7097ecd1f6a7bd1383847ef9a5b1",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/darwin/ios/BUILD.gn",
      "new_id": "35a50dbf024508a81217272db7e33f36ca792123",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/darwin/ios/BUILD.gn"
    },
    {
      "type": "modify",
      "old_id": "813c475ecd152aba1d6a7bf2a1c5722cdc0807fa",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/darwin/ios/framework/Source/AccessibilityFeaturesTests.swift",
      "new_id": "f564433a98f5940468b13987f90bacbb1d39c46c",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/darwin/ios/framework/Source/AccessibilityFeaturesTests.swift"
    },
    {
      "type": "modify",
      "old_id": "ac914009d73c4f17b80e69aa0ea62e72c771b550",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/darwin/ios/framework/Source/ConnectionCollectionTest.swift",
      "new_id": "cc7984c9bad86d02210bcea7432db8931419cf51",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/darwin/ios/framework/Source/ConnectionCollectionTest.swift"
    },
    {
      "type": "modify",
      "old_id": "d47a343b0214d210744f337ec231c287df6d78a5",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/shell/platform/darwin/ios/framework/Source/LaunchEngineTest.swift",
      "new_id": "17f5212311f06f0a30f6caa86dd1c2c595046d5e",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/shell/platform/darwin/ios/framework/Source/LaunchEngineTest.swift"
    },
    {
      "type": "modify",
      "old_id": "7a31a585282258fb44b018057d569f08031a1065",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj",
      "new_id": "e30a20063dea0678041b024d27b4a7a9bc8f0bac",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj"
    }
  ]
}
