@@ -2790,4 +2790,111 @@ - (BOOL)validateOneVisualEffectView:(UIView*)visualEffectView
27902790 return NO ;
27912791}
27922792
2793+ - (void )testDisposingViewInCompositionOrderDoNotCrash {
2794+ flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2795+ auto thread_task_runner = CreateNewThread (" FlutterPlatformViewsTest" );
2796+ flutter::TaskRunners runners (/* label=*/ self.name .UTF8String ,
2797+ /* platform=*/ thread_task_runner,
2798+ /* raster=*/ thread_task_runner,
2799+ /* ui=*/ thread_task_runner,
2800+ /* io=*/ thread_task_runner);
2801+ auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
2802+ auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2803+ /* delegate=*/ mock_delegate,
2804+ /* rendering_api=*/ flutter::IOSRenderingAPI::kSoftware ,
2805+ /* platform_views_controller=*/ flutterPlatformViewsController,
2806+ /* task_runners=*/ runners);
2807+
2808+ UIView* mockFlutterView = [[[UIView alloc ] initWithFrame: CGRectMake (0 , 0 , 500 , 500 )] autorelease ];
2809+ flutterPlatformViewsController->SetFlutterView (mockFlutterView);
2810+
2811+ FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2812+ [[FlutterPlatformViewsTestMockFlutterPlatformFactory new ] autorelease ];
2813+ flutterPlatformViewsController->RegisterViewFactory (
2814+ factory, @" MockFlutterPlatformView" ,
2815+ FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2816+ FlutterResult result = ^(id result) {
2817+ };
2818+
2819+ flutterPlatformViewsController->OnMethodCall (
2820+ [FlutterMethodCall
2821+ methodCallWithMethodName: @" create"
2822+ arguments: @{@" id" : @0 , @" viewType" : @" MockFlutterPlatformView" }],
2823+ result);
2824+ flutterPlatformViewsController->OnMethodCall (
2825+ [FlutterMethodCall
2826+ methodCallWithMethodName: @" create"
2827+ arguments: @{@" id" : @1 , @" viewType" : @" MockFlutterPlatformView" }],
2828+ result);
2829+
2830+ {
2831+ // **** First frame, view id 0, 1 in the composition_order_, disposing view 0 is called. **** //
2832+ // No view should be disposed, or removed from the composition order.
2833+ flutterPlatformViewsController->BeginFrame (SkISize::Make (300 , 300 ));
2834+ flutter::MutatorsStack stack;
2835+ SkMatrix finalMatrix;
2836+ auto embeddedViewParams0 =
2837+ std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make (300 , 300 ), stack);
2838+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (0 , std::move (embeddedViewParams0));
2839+ flutterPlatformViewsController->CompositeEmbeddedView (0 );
2840+
2841+ auto embeddedViewParams1 =
2842+ std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make (300 , 300 ), stack);
2843+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (1 , std::move (embeddedViewParams1));
2844+ flutterPlatformViewsController->CompositeEmbeddedView (1 );
2845+ XCTAssertEqual (flutterPlatformViewsController->EmbeddedViewCount (), 2UL );
2846+
2847+ XCTestExpectation* expectation = [self expectationWithDescription: @" dispose call ended." ];
2848+ FlutterResult disposeResult = ^(id result) {
2849+ [expectation fulfill ];
2850+ };
2851+
2852+ flutterPlatformViewsController->OnMethodCall (
2853+ [FlutterMethodCall methodCallWithMethodName: @" dispose" arguments: @0 ], disposeResult);
2854+ [self waitForExpectationsWithTimeout: 30 handler: nil ];
2855+
2856+ const SkImageInfo image_info = SkImageInfo::MakeN32Premul (1000 , 1000 );
2857+ sk_sp<SkSurface> mock_sk_surface = SkSurface::MakeRaster (image_info);
2858+ flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
2859+ auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
2860+ std::move (mock_sk_surface), framebuffer_info,
2861+ [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true ; },
2862+ /* frame_size=*/ SkISize::Make (800 , 600 ));
2863+ XCTAssertTrue (
2864+ flutterPlatformViewsController->SubmitFrame (nullptr , nullptr , std::move (mock_surface)));
2865+
2866+ // Disposing won't remove embedded views until the view is removed from the composition_order_
2867+ XCTAssertEqual (flutterPlatformViewsController->EmbeddedViewCount (), 2UL );
2868+ XCTAssertNotNil (flutterPlatformViewsController->GetPlatformViewByID (0 ));
2869+ XCTAssertNotNil (flutterPlatformViewsController->GetPlatformViewByID (1 ));
2870+ }
2871+
2872+ {
2873+ // **** Second frame, view id 1 in the composition_order_, no disposing view is called, **** //
2874+ // View 0 is removed from the composition order in this frame, hence also disposed.
2875+ flutterPlatformViewsController->BeginFrame (SkISize::Make (300 , 300 ));
2876+ flutter::MutatorsStack stack;
2877+ SkMatrix finalMatrix;
2878+ auto embeddedViewParams1 =
2879+ std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make (300 , 300 ), stack);
2880+ flutterPlatformViewsController->PrerollCompositeEmbeddedView (1 , std::move (embeddedViewParams1));
2881+ flutterPlatformViewsController->CompositeEmbeddedView (1 );
2882+
2883+ const SkImageInfo image_info = SkImageInfo::MakeN32Premul (1000 , 1000 );
2884+ sk_sp<SkSurface> mock_sk_surface = SkSurface::MakeRaster (image_info);
2885+ flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
2886+ auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
2887+ std::move (mock_sk_surface), framebuffer_info,
2888+ [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true ; },
2889+ /* frame_size=*/ SkISize::Make (800 , 600 ));
2890+ XCTAssertTrue (
2891+ flutterPlatformViewsController->SubmitFrame (nullptr , nullptr , std::move (mock_surface)));
2892+
2893+ // Disposing won't remove embedded views until the view is removed from the composition_order_
2894+ XCTAssertEqual (flutterPlatformViewsController->EmbeddedViewCount (), 1UL );
2895+ XCTAssertNil (flutterPlatformViewsController->GetPlatformViewByID (0 ));
2896+ XCTAssertNotNil (flutterPlatformViewsController->GetPlatformViewByID (1 ));
2897+ }
2898+ }
2899+
27932900@end
0 commit comments