mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[web] clear surfaces on hot restart (flutter/engine#28675)
* [web] clear surfaces on hot restart
This commit is contained in:
parent
85ef33904e
commit
74dcaafe7a
@ -361,6 +361,17 @@ void registerHotRestartListener(ui.VoidCallback listener) {
|
||||
_hotRestartListeners.add(listener);
|
||||
}
|
||||
|
||||
/// Pretends that hot restart is about to happen.
|
||||
///
|
||||
/// Useful in tests to check that the engine performs appropriate clean-ups,
|
||||
/// such as removing static DOM listeners, prior to allowing the Dart runtime
|
||||
/// to re-initialize the program.
|
||||
void debugEmulateHotRestart() {
|
||||
for (final ui.VoidCallback listener in _hotRestartListeners) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
|
||||
/// This method performs one-time initialization of the Web environment that
|
||||
/// supports the Flutter framework.
|
||||
///
|
||||
|
||||
@ -4,19 +4,33 @@
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../../engine.dart';
|
||||
import '../util.dart';
|
||||
import 'embedded_views.dart';
|
||||
import 'surface.dart';
|
||||
|
||||
/// Caches surfaces used to overlay platform views.
|
||||
class SurfaceFactory {
|
||||
/// The cache singleton.
|
||||
static final SurfaceFactory instance =
|
||||
SurfaceFactory(HtmlViewEmbedder.maximumSurfaces);
|
||||
/// The lazy-initialized singleton surface factory.
|
||||
///
|
||||
/// [debugClear] causes this singleton to be reinitialized.
|
||||
static SurfaceFactory get instance =>
|
||||
_instance ??= SurfaceFactory(HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
/// Returns the raw (potentially uninitialized) value of the singleton.
|
||||
///
|
||||
/// Useful in tests for checking the lifecycle of this class.
|
||||
static SurfaceFactory? get debugUninitializedInstance => _instance;
|
||||
|
||||
static SurfaceFactory? _instance;
|
||||
|
||||
SurfaceFactory(this.maximumSurfaces)
|
||||
: assert(maximumSurfaces >= 1,
|
||||
'The maximum number of surfaces must be at least 1');
|
||||
'The maximum number of surfaces must be at least 1') {
|
||||
if (assertionsEnabled) {
|
||||
registerHotRestartListener(debugClear);
|
||||
}
|
||||
}
|
||||
|
||||
/// The base surface to paint on. This is the default surface which will be
|
||||
/// painted to. If there are no platform views, then this surface will receive
|
||||
@ -168,7 +182,10 @@ class SurfaceFactory {
|
||||
for (final Surface surface in _liveSurfaces) {
|
||||
surface.dispose();
|
||||
}
|
||||
baseSurface.dispose();
|
||||
backupSurface.dispose();
|
||||
_liveSurfaces.clear();
|
||||
_cache.clear();
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,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 '../matchers.dart';
|
||||
import 'common.dart';
|
||||
@ -76,6 +77,40 @@ void testMain() {
|
||||
expect(factory.isLive(surface), isFalse);
|
||||
});
|
||||
|
||||
test('hot restart', () {
|
||||
void expectDisposed(Surface surface) {
|
||||
expect(surface.htmlCanvas!.isConnected, isFalse);
|
||||
}
|
||||
|
||||
final SurfaceFactory originalFactory = SurfaceFactory.instance;
|
||||
expect(SurfaceFactory.debugUninitializedInstance, isNotNull);
|
||||
|
||||
// Cause the surface and its canvas to be attached to the page
|
||||
originalFactory.baseSurface.acquireFrame(const ui.Size(10, 10));
|
||||
originalFactory.baseSurface.addToScene();
|
||||
expect(originalFactory.baseSurface.htmlCanvas!.isConnected, isTrue);
|
||||
|
||||
// Create a few overlay surfaces
|
||||
final List<Surface> overlays = <Surface>[];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
overlays.add(originalFactory.getSurface()
|
||||
..acquireFrame(const ui.Size(10, 10))
|
||||
..addToScene());
|
||||
}
|
||||
expect(originalFactory.debugSurfaceCount, 5);
|
||||
|
||||
originalFactory.backupSurface.acquireFrame(const ui.Size(10, 10));
|
||||
originalFactory.backupSurface.addToScene();
|
||||
expect(originalFactory.backupSurface.htmlCanvas!.isConnected, isTrue);
|
||||
|
||||
// Trigger hot restart clean-up logic and check that we indeed clean up.
|
||||
debugEmulateHotRestart();
|
||||
expect(SurfaceFactory.debugUninitializedInstance, isNull);
|
||||
expectDisposed(originalFactory.baseSurface);
|
||||
expectDisposed(originalFactory.backupSurface);
|
||||
overlays.forEach(expectDisposed);
|
||||
expect(originalFactory.debugSurfaceCount, 2);
|
||||
});
|
||||
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/60040
|
||||
}, skip: isIosSafari);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user