Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[web] Do not wipe the PlatformViewManager when disposing of a view. #49991

Merged
merged 4 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,7 @@ class HtmlViewEmbedder {
// are going to be added back. Moving rather than removing and re-adding
// the view helps it maintain state.
disposeViews(diffResult.viewsToRemove
.where((int view) => !diffResult.viewsToAdd.contains(view))
.toSet());
.where((int view) => !diffResult.viewsToAdd.contains(view)));
_activeCompositionOrder.addAll(_compositionOrder);
unusedViews.removeAll(_compositionOrder);

Expand Down Expand Up @@ -510,7 +509,7 @@ class HtmlViewEmbedder {
);
}

void disposeViews(Set<int> viewsToDispose) {
void disposeViews(Iterable<int> viewsToDispose) {
for (final int viewId in viewsToDispose) {
// Remove viewId from the _viewClipChains Map, and then from the DOM.
final ViewClipChain? clipChain = _viewClipChains.remove(viewId);
Expand Down Expand Up @@ -659,8 +658,7 @@ class HtmlViewEmbedder {

/// Disposes the state of this view embedder.
void dispose() {
final Set<int> allViews = PlatformViewManager.instance.debugClear();
disposeViews(allViews);
disposeViews(_viewClipChains.keys.toList());
_context = EmbedderFrameContext();
_currentCompositionParams.clear();
debugCleanupSvgClipPaths();
Expand Down
8 changes: 2 additions & 6 deletions lib/web_ui/lib/src/engine/platform_views/content_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,12 @@ class PlatformViewManager {
bool isVisible(int viewId) => !isInvisible(viewId);

/// Clears the state. Used in tests.
///
/// Returns the set of know view ids, so they can be cleaned up.
Set<int> debugClear() {
final Set<int> result = _contents.keys.toSet();
result.forEach(clearPlatformView);
void debugClear() {
_contents.keys.toList().forEach(clearPlatformView);
_factories.clear();
_contents.clear();
_invisibleViews.clear();
_viewIdToType.clear();
return result;
}
}

Expand Down
24 changes: 24 additions & 0 deletions lib/web_ui/test/canvaskit/multi_view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import '../common/matchers.dart';
import 'common.dart';
Expand Down Expand Up @@ -68,5 +69,28 @@ void testMain() {
isNull,
);
});

// Issue https://github.com/flutter/flutter/issues/142094
test('does not reset platform view factories when disposing a view', () async {
expect(PlatformViewManager.instance.knowsViewType('self-test'), isFalse);

final EngineFlutterView view = EngineFlutterView(
EnginePlatformDispatcher.instance, createDomElement('multi-view'));
EnginePlatformDispatcher.instance.viewManager.registerView(view);
expect(
CanvasKitRenderer.instance.debugGetRasterizerForView(view),
isNotNull,
);

EnginePlatformDispatcher.instance.viewManager
.disposeAndUnregisterView(view.viewId);
expect(
CanvasKitRenderer.instance.debugGetRasterizerForView(view),
isNull,
);

expect(PlatformViewManager.instance.knowsViewType(ui_web.PlatformViewRegistry.defaultVisibleViewType), isTrue);
expect(PlatformViewManager.instance.knowsViewType(ui_web.PlatformViewRegistry.defaultInvisibleViewType), isTrue);
});
});
}