diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 5978c1137a4b0..cd4188e88a18f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -876,7 +876,17 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, current_composition_params_.erase(viewId); clip_count_.erase(viewId); views_to_recomposite_.erase(viewId); + slices_.erase(viewId); } + + composition_order_.erase( + std::remove_if(composition_order_.begin(), composition_order_.end(), + [views_to_dispose = views_to_dispose_](const int64_t viewId) { + FML_DCHECK(views_to_dispose.count(viewId) < 2); + return views_to_dispose.count(viewId) > 0; + }), + composition_order_.end()); + views_to_dispose_.clear(); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index b3522ec48a21e..014c5f4fba27d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -2790,4 +2790,77 @@ - (BOOL)validateOneVisualEffectView:(UIView*)visualEffectView return NO; } +- (void)testDisposingViewInCompositionOrderDoNotCrash { + flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate; + auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest"); + flutter::TaskRunners runners(/*label=*/self.name.UTF8String, + /*platform=*/thread_task_runner, + /*raster=*/thread_task_runner, + /*ui=*/thread_task_runner, + /*io=*/thread_task_runner); + auto flutterPlatformViewsController = std::make_shared(); + auto platform_view = std::make_unique( + /*delegate=*/mock_delegate, + /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*platform_views_controller=*/flutterPlatformViewsController, + /*task_runners=*/runners); + + UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; + flutterPlatformViewsController->SetFlutterView(mockFlutterView); + + FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = + [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + FlutterResult result = ^(id result) { + }; + + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}], + result); + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}], + result); + + flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300)); + flutter::MutatorsStack stack; + SkMatrix finalMatrix; + auto embeddedViewParams0 = + std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); + flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams0)); + flutterPlatformViewsController->CompositeEmbeddedView(0); + + auto embeddedViewParams1 = + std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); + flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1)); + flutterPlatformViewsController->CompositeEmbeddedView(1); + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 2UL); + + XCTestExpectation* expectation = [self expectationWithDescription:@"dispose call ended."]; + FlutterResult disposeResult = ^(id result) { + [expectation fulfill]; + }; + + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall methodCallWithMethodName:@"dispose" arguments:@0], disposeResult); + [self waitForExpectationsWithTimeout:30 handler:nil]; + + const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); + sk_sp mock_sk_surface = SkSurface::MakeRaster(image_info); + flutter::SurfaceFrame::FramebufferInfo framebuffer_info; + auto mock_surface = std::make_unique( + std::move(mock_sk_surface), framebuffer_info, + [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, + /*frame_size=*/SkISize::Make(800, 600)); + XCTAssertTrue( + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface))); + + XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL); +} + @end